install.lib.php 20 KB

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