install.lib.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * @param Symfony\Component\Translation\Translator $translator
  5. * @return null|string
  6. */
  7. function drawRequirements($translator)
  8. {
  9. $requirements = getRequirements();
  10. $html = null;
  11. $html .= '<tr>
  12. <td>
  13. '.$translator->trans('Required').'
  14. </td>
  15. <td>
  16. </td>
  17. </tr>';
  18. foreach ($requirements['required'] as $extension => $req) {
  19. $checkExtension = check_extension(
  20. $extension,
  21. $translator->trans('Yes'),
  22. $translator->trans('No')
  23. );
  24. $html .= '<tr>
  25. <td>
  26. <a href="'.$req['url'].'">'.$extension.'</a>
  27. </td>
  28. <td>
  29. '.$checkExtension.'
  30. </td>
  31. </tr>';
  32. }
  33. $html .= '<tr>
  34. <td>
  35. '.$translator->trans('Optional').'
  36. </td>
  37. <td>
  38. </td>
  39. </tr>';
  40. foreach ($requirements['optional'] as $extension => $req) {
  41. $checkExtension = check_extension(
  42. $extension,
  43. $translator->trans('Yes'),
  44. $translator->trans('No')
  45. );
  46. $html .= '<tr>
  47. <td>
  48. <a href="'.$req['url'].'">'.$extension.'</a>
  49. </td>
  50. <td>
  51. '.$checkExtension.'
  52. </td>
  53. </tr>';
  54. }
  55. return $html;
  56. }
  57. function drawOptions($translator)
  58. {
  59. $options = getOptions($translator);
  60. $html = null;
  61. foreach ($options as $option) {
  62. $html .= '<tr>
  63. <td>
  64. <a href="'.$option['url'].'">'.$option['name'].'</a>
  65. </td>
  66. <td>
  67. '.$option['recommended'].'
  68. </td>
  69. <td>
  70. '.$option['current'].'
  71. </td>
  72. </tr>';
  73. }
  74. return $html;
  75. }
  76. /**
  77. * @param Symfony\Component\Translation\Translator $translator
  78. * @return array
  79. */
  80. function getOptions($translator)
  81. {
  82. return array(
  83. array(
  84. 'name' => 'Safe Mode',
  85. 'url' => 'http://php.net/manual/features.safe-mode.php',
  86. 'recommended' => Display::label('OFF', 'success'),
  87. 'current' => check_php_setting('safe_mode', 'OFF'),
  88. ),
  89. array(
  90. 'name' => 'Display Errors',
  91. 'url' => 'http://php.net/manual/ref.errorfunc.php#ini.display-errors',
  92. 'recommended' => Display::label('ON', 'success'),
  93. 'current' => check_php_setting('display_errors', 'OFF'),
  94. ),
  95. array(
  96. 'name' => 'File Uploads',
  97. 'url' => 'http://php.net/manual/ini.core.php#ini.file-uploads',
  98. 'recommended' => Display::label('OFF', 'success'),
  99. 'current' => check_php_setting('file_uploads', 'ON'),
  100. ),
  101. array(
  102. 'name' => 'Magic Quotes GPC',
  103. 'url' => 'http://php.net/manual/ref.info.php#ini.magic-quotes-gpc',
  104. 'recommended' => Display::label('OFF', 'success'),
  105. 'current' => check_php_setting('magic_quotes_gpc', 'OFF'),
  106. ),
  107. array(
  108. 'name' => 'Magic Quotes Runtime',
  109. 'url' => 'http://php.net/manual/ref.info.php#ini.magic-quotes-runtime',
  110. 'recommended' => Display::label('OFF', 'success'),
  111. 'current' => check_php_setting('magic_quotes_runtime', 'OFF'),
  112. ),
  113. array(
  114. 'name' => 'Register Globals',
  115. 'url' => 'http://php.net/manual/security.globals.php',
  116. 'recommended' => Display::label('OFF', 'success'),
  117. 'current' => check_php_setting('register_globals', 'OFF'),
  118. ),
  119. array(
  120. 'name' => 'Session auto start',
  121. 'url' => 'http://php.net/manual/ref.session.php#ini.session.auto-start',
  122. 'recommended' => Display::label('OFF', 'success'),
  123. 'current' => check_php_setting('auto_start', 'OFF'),
  124. ),
  125. array(
  126. 'name' => 'Short Open Tag',
  127. 'url' => 'http://php.net/manual/ini.core.php#ini.short-open-tag',
  128. 'recommended' => Display::label('OFF', 'success'),
  129. 'current' => check_php_setting('short_open_tag', 'OFF'),
  130. ),
  131. array(
  132. 'name' => 'Cookie HTTP Only',
  133. 'url' => 'http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-httponly',
  134. 'recommended' => Display::label('ON', 'success'),
  135. 'current' => check_php_setting('session.cookie_httponly', 'ON'),
  136. ),
  137. array(
  138. 'name' => 'Maximum upload file size',
  139. 'url' => 'http://php.net/manual/ini.core.php#ini.upload-max-filesize',
  140. 'recommended' => Display::label('>= '.REQUIRED_MIN_UPLOAD_MAX_FILESIZE.'M', 'success'),
  141. 'current' => compare_setting_values(ini_get('upload_max_filesize'), REQUIRED_MIN_UPLOAD_MAX_FILESIZE),
  142. ),
  143. array(
  144. 'name' => 'Maximum post size',
  145. 'url' => 'http://php.net/manual/ini.core.php#ini.post-max-size',
  146. 'recommended' => Display::label('>= '.REQUIRED_MIN_POST_MAX_SIZE.'M', 'success'),
  147. 'current' => compare_setting_values(ini_get('post_max_size'), REQUIRED_MIN_POST_MAX_SIZE),
  148. ),
  149. array(
  150. 'name' => 'Memory Limit',
  151. 'url' => 'http://www.php.net/manual/en/ini.core.php#ini.memory-limit',
  152. 'recommended' => Display::label('>= '.REQUIRED_MIN_MEMORY_LIMIT.'M', 'success'),
  153. 'current' => compare_setting_values(ini_get('memory_limit'), REQUIRED_MIN_MEMORY_LIMIT),
  154. )
  155. );
  156. }
  157. function translate($variable)
  158. {
  159. global $app;
  160. return $app['translator']->trans($variable);
  161. }
  162. /**
  163. * This function checks if a php extension exists or not and returns an HTML status string.
  164. *
  165. * @param string Name of the PHP extension to be checked
  166. * @param string Text to show when extension is available (defaults to 'Yes')
  167. * @param string Text to show when extension is available (defaults to 'No')
  168. * @param boolean Whether this extension is optional (in this case show unavailable text in orange rather than red)
  169. * @return string HTML string reporting the status of this extension. Language-aware.
  170. * @author Christophe Gesch??
  171. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  172. * @author Yannick Warnier <yannick.warnier@dokeos.com>
  173. * @version Dokeos 1.8.1, May 2007
  174. */
  175. function check_extension($extension_name, $return_success = 'Yes', $return_failure = 'No', $optional = false)
  176. {
  177. if (extension_loaded($extension_name)) {
  178. return Display::label($return_success, 'success');
  179. } else {
  180. if ($optional) {
  181. return Display::label($return_failure, 'warning');
  182. //return '<strong><font color="#ff9900">'.$return_failure.'</font></strong>';
  183. } else {
  184. return Display::label($return_failure, 'important');
  185. //return '<strong><font color="red">'.$return_failure.'</font></strong>';
  186. }
  187. }
  188. }
  189. /**
  190. * This function checks whether a php setting matches the recommended value
  191. *
  192. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  193. * @version Dokeos 1.8, august 2006
  194. */
  195. function check_php_setting($php_setting, $recommended_value, $return_success = false, $return_failure = false)
  196. {
  197. $current_php_value = get_php_setting($php_setting);
  198. if ($current_php_value == $recommended_value) {
  199. return Display::label($current_php_value.' '.$return_success, 'success');
  200. } else {
  201. return Display::label($current_php_value.' '.$return_success, 'important');
  202. }
  203. }
  204. /**
  205. * Returns a textual value ('ON' or 'OFF') based on a requester 2-state ini- configuration setting.
  206. *
  207. * @param string $val a php ini value
  208. * @return boolean: ON or OFF
  209. * @author Joomla <http://www.joomla.org>
  210. */
  211. function get_php_setting($val)
  212. {
  213. return ini_get($val) == '1' ? 'ON' : 'OFF';
  214. }
  215. function compare_setting_values($current_value, $wanted_value)
  216. {
  217. $current_value_string = $current_value;
  218. $current_value = (float) $current_value;
  219. $wanted_value = (float) $wanted_value;
  220. if ($current_value >= $wanted_value) {
  221. return Display::label($current_value_string, 'success');
  222. } else {
  223. return Display::label($current_value_string, 'important');
  224. }
  225. }
  226. function drawPermissionsSettings($app)
  227. {
  228. $html = null;
  229. // DIRECTORY AND FILE PERMISSIONS
  230. $html .= '<div class="RequirementContent">';
  231. $course_attempt_name = '__XxTestxX__';
  232. $course_dir = $app['path.courses'].$course_attempt_name;
  233. // Just in case.
  234. if (is_file($course_dir.'/test.txt')) {
  235. unlink($course_dir.'/test.txt');
  236. }
  237. if (is_dir($course_dir)) {
  238. rmdir($course_dir);
  239. }
  240. $perms_dir = array(0777, 0755, 0775, 0770, 0750, 0700);
  241. $perms_fil = array(0666, 0644, 0664, 0660, 0640, 0600);
  242. $course_test_was_created = false;
  243. $dir_perm_verified = 0777;
  244. foreach ($perms_dir as $perm) {
  245. $r = @mkdir($course_dir, $perm);
  246. if ($r === true) {
  247. $dir_perm_verified = $perm;
  248. $course_test_was_created = true;
  249. break;
  250. }
  251. }
  252. $fil_perm_verified = 0666;
  253. $file_course_test_was_created = false;
  254. if (is_dir($course_dir)) {
  255. foreach ($perms_fil as $perm) {
  256. if ($file_course_test_was_created == true) {
  257. break;
  258. }
  259. $r = touch($course_dir.'/test.php', $perm);
  260. if ($r === true) {
  261. $fil_perm_verified = $perm;
  262. if (check_course_script_interpretation($course_dir, $course_attempt_name, 'test.php')) {
  263. $file_course_test_was_created = true;
  264. }
  265. }
  266. }
  267. }
  268. @unlink($course_dir.'/test.php');
  269. @rmdir($course_dir);
  270. $app['session']->set('permissions_for_new_directories', decoct($dir_perm_verified));
  271. $app['session']->set('permissions_for_new_files', decoct($fil_perm_verified));
  272. $dir_perm = Display::label('0'.decoct($dir_perm_verified), 'info');
  273. $file_perm = Display::label('0'.decoct($fil_perm_verified), 'info');
  274. $course_test_was_created = ($course_test_was_created == true && $file_course_test_was_created == true) ? Display::label(translate('Yes'), 'success') : Display::label(translate('No'), 'important');
  275. $html .= '<table class="table">
  276. <tr>
  277. <td class="requirements-item">[chamilo]/config</td>
  278. <td class="requirements-value">'.check_writable_root_path('config/').'</td>
  279. </tr>
  280. <tr>
  281. <td class="requirements-item">[chamilo]/data</td>
  282. <td class="requirements-value">'.check_writable_root_path('data').'</td>
  283. </tr>
  284. <tr>
  285. <td class="requirements-item">[chamilo]/logs</td>
  286. <td class="requirements-value">'.check_writable_root_path('logs').'</td>
  287. </tr>
  288. <tr>
  289. <td class="requirements-item">'.translate('CourseTestWasCreated').'</td>
  290. <td class="requirements-value">'.$course_test_was_created.' </td>
  291. </tr>
  292. <tr>
  293. <td class="requirements-item">'.translate('PermissionsForNewDirs').'</td>
  294. <td class="requirements-value">'.$dir_perm.' </td>
  295. </tr>
  296. <tr>
  297. <td class="requirements-item">'.translate('PermissionsForNewFiles').'</td>
  298. <td class="requirements-value">'.$file_perm.' </td>
  299. </tr>';
  300. $html .= ' </table>';
  301. $html .= ' </div>';
  302. $html .= '</div>';
  303. $error = false;
  304. // First, attempt to set writing permissions if we don't have them yet
  305. $perm = $app['session']->get('permissions_for_new_directories');
  306. $perm_file = $app['session']->get('permissions_for_new_files');
  307. $notwritable = array();
  308. $checked_writable = api_get_path(SYS_CONFIG_PATH);
  309. if (!is_writable($checked_writable)) {
  310. $notwritable[] = $checked_writable;
  311. @chmod($checked_writable, $perm);
  312. }
  313. $checked_writable = api_get_path(SYS_DATA_PATH);
  314. if (!is_writable($checked_writable)) {
  315. $notwritable[] = $checked_writable;
  316. @chmod($checked_writable, $perm);
  317. }
  318. $checked_writable = api_get_path(SYS_DEFAULT_COURSE_DOCUMENT_PATH).'images/';
  319. if (!is_writable($checked_writable)) {
  320. $notwritable[] = $checked_writable;
  321. @chmod($checked_writable, $perm);
  322. }
  323. $checked_writable = api_get_path(SYS_ARCHIVE_PATH);
  324. if (!is_writable($checked_writable)) {
  325. $notwritable[] = $checked_writable;
  326. @chmod($checked_writable, $perm);
  327. }
  328. $checked_writable = api_get_path(SYS_LOG_PATH);
  329. if (!is_writable($checked_writable)) {
  330. $notwritable[] = $checked_writable;
  331. @chmod($checked_writable, $perm);
  332. }
  333. /*$checked_writable = api_get_path(SYS_COURSE_PATH);
  334. if (!is_writable($checked_writable)) {
  335. $notwritable[] = $checked_writable;
  336. @chmod($checked_writable, $perm);
  337. }*/
  338. if ($course_test_was_created == false || $file_course_test_was_created == false) {
  339. $error = true;
  340. }
  341. /*$checked_writable = api_get_path(SYS_PATH).'home/';
  342. if (!is_writable($checked_writable)) {
  343. $notwritable[] = realpath($checked_writable);
  344. @chmod($checked_writable, $perm);
  345. }*/
  346. /*$checked_writable = api_get_path(CONFIGURATION_PATH).'configuration.php';
  347. if (file_exists($checked_writable) && !is_writable($checked_writable)) {
  348. $notwritable[] = $checked_writable;
  349. @chmod($checked_writable, $perm_file);
  350. }*/
  351. // Second, if this fails, report an error
  352. // The user would have to adjust the permissions manually
  353. if (count($notwritable) > 0) {
  354. $html .= '<div class="error-message">';
  355. $html .= '<center><h3>'.translate('Warning').'</h3></center>';
  356. $html .= sprintf(
  357. translate('NoWritePermissionPleaseReadInstallGuide'),
  358. '</font>
  359. <a href="../../documentation/installation_guide.html" target="blank">',
  360. '</a> <font color="red">'
  361. );
  362. $html .= '</div>';
  363. $html .= '<ul>';
  364. foreach ($notwritable as $value) {
  365. $html .= '<li>'.$value.'</li>';
  366. }
  367. $html .= '</ul>';
  368. } elseif (file_exists(api_get_path(CONFIGURATION_PATH).'configuration.php')) {
  369. // Check wether a Chamilo configuration file already exists.
  370. $html .= '<div class="warning-message"><h4><center>';
  371. $html .= translate('WarningExistingDokeosInstallationDetected');
  372. $html .= '</center></h4></div>';
  373. }
  374. return $html;
  375. }
  376. function check_course_script_interpretation($course_dir, $course_attempt_name, $file = 'test.php')
  377. {
  378. $output = false;
  379. //Write in file
  380. $file_name = $course_dir.'/'.$file;
  381. $content = '<?php echo "123"; exit;';
  382. if (is_writable($file_name)) {
  383. if ($handler = @fopen($file_name, "w")) {
  384. //write content
  385. if (fwrite($handler , $content)) {
  386. $file = api_get_path(SYS_COURSE_PATH).$course_attempt_name.'/'.$file;
  387. if (file_exists($file)) {
  388. return true;
  389. }
  390. //You can't access to a course file like this. You will be prompted to the installation process.
  391. //If you access
  392. $sock_errno = '';
  393. $sock_errmsg = '';
  394. $url = api_get_path(WEB_COURSE_PATH).$course_attempt_name.'/'.$file;
  395. $parsed_url = parse_url($url);
  396. //$scheme = isset($parsedUrl['scheme']) ? $parsedUrl['scheme'] : ''; //http
  397. $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
  398. $path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
  399. $port = isset($parsed_url['port']) ? $parsed_url['port'] : '80';
  400. //Check fsockopen
  401. if ($fp = @fsockopen(str_replace('http://', '', $url), -1, $sock_errno, $sock_errmsg, 60)) {
  402. $out = "GET $path HTTP/1.1\r\n";
  403. $out .= "Host: $host\r\n";
  404. $out .= "Connection: Close\r\n\r\n";
  405. fwrite($fp, $out);
  406. while (!feof($fp)) {
  407. $result = str_replace("\r\n", '', fgets($fp, 128));
  408. if (!empty($result) && $result == '123') {
  409. $output = true;
  410. }
  411. }
  412. fclose($fp);
  413. //Check allow_url_fopen
  414. } elseif (ini_get('allow_url_fopen')) {
  415. if ($fp = @fopen($url, 'r')) {
  416. while ($result = fgets($fp, 1024)) {
  417. if (!empty($result) && $result == '123') {
  418. $output = true;
  419. }
  420. }
  421. fclose($fp);
  422. }
  423. // Check if has support for cURL
  424. } elseif (function_exists('curl_init')) {
  425. $ch = curl_init();
  426. curl_setopt($ch, CURLOPT_HEADER, 0);
  427. curl_setopt($ch, CURLOPT_URL, $url);
  428. //curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  429. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  430. $result = curl_exec($ch);
  431. if (!empty($result) && $result == '123') {
  432. $output = true;
  433. }
  434. curl_close($ch);
  435. }
  436. }
  437. @fclose($handler);
  438. }
  439. }
  440. return $output;
  441. }
  442. /**
  443. * This function checks if the given folder is writable
  444. */
  445. function check_writable_root_path($folder, $suggestion = false)
  446. {
  447. if (is_writable(api_get_path(SYS_PATH).$folder)) {
  448. return Display::label(translate('Writable'), 'success');
  449. } else {
  450. if ($suggestion) {
  451. return Display::label(translate('NotWritable'), 'info');
  452. } else {
  453. return Display::label(translate('NotWritable'), 'important');
  454. }
  455. }
  456. }