PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/update.php

http://github.com/symphonycms/symphony-2
PHP | 553 lines | 404 code | 118 blank | 31 comment | 47 complexity | 0f4ec1cfb467d8ce0ccede392ae80b69 MD5 | raw file
  1. <?php
  2. error_reporting(E_ALL ^ E_NOTICE);
  3. function __errorHandler($errno=NULL, $errstr, $errfile=NULL, $errline=NULL, $errcontext=NULL){
  4. return;
  5. }
  6. function tableContainsField($table, $field){
  7. $sql = "DESC `{$table}` `{$field}`";
  8. $results = Frontend::instance()->Database->fetch($sql);
  9. return (is_array($results) && !empty($results));
  10. }
  11. function writeConfig($dest, $conf, $mode){
  12. $string = "<?php\n";
  13. $string .= "\n\t\$settings = array(";
  14. foreach($conf as $group => $data){
  15. $string .= "\r\n\r\n\r\n\t\t###### ".strtoupper($group)." ######";
  16. $string .= "\r\n\t\t'$group' => array(";
  17. foreach($data as $key => $value){
  18. $string .= "\r\n\t\t\t'$key' => ".(strlen($value) > 0 ? "'".addslashes($value)."'" : 'NULL').",";
  19. }
  20. $string .= "\r\n\t\t),";
  21. $string .= "\r\n\t\t########";
  22. }
  23. $string .= "\r\n\t);\n\n";
  24. return General::writeFile($dest . '/config.php', $string, $mode);
  25. }
  26. function loadOldStyleConfig(){
  27. $config = preg_replace(array('/^<\?php/i', '/\?>$/i', '/if\(\!defined\([^\r\n]+/i', '/require_once[^\r\n]+/i'), NULL, file_get_contents('manifest/config.php'));
  28. if(@eval($config) === false){
  29. throw new Exception('Failed to load existing config');
  30. }
  31. return $settings;
  32. }
  33. function render($output){
  34. header('Expires: Mon, 12 Dec 1982 06:14:00 GMT');
  35. header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
  36. header('Cache-Control: no-cache, must-revalidate, max-age=0');
  37. header('Pragma: no-cache');
  38. header(sprintf('Content-Length: %d', strlen($output)));
  39. echo $output;
  40. exit;
  41. }
  42. define('DOCROOT', rtrim(dirname(__FILE__), '/'));
  43. define('DOMAIN', rtrim(rtrim($_SERVER['HTTP_HOST'], '/') . dirname($_SERVER['PHP_SELF']), '/'));
  44. require_once(DOCROOT . '/symphony/lib/boot/bundle.php');
  45. require_once(TOOLKIT . '/class.general.php');
  46. set_error_handler('__errorHandler');
  47. define('kVERSION', '2.2.5');
  48. define('kCHANGELOG', 'http://symphony-cms.com/download/releases/version/2.2.5/');
  49. define('kINSTALL_ASSET_LOCATION', './symphony/assets/installer');
  50. define('kINSTALL_FILENAME', basename(__FILE__));
  51. $shell = '<?xml version="1.0" encoding="utf-8"?>
  52. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
  53. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  54. <head>
  55. <title>Update Existing Installation</title>
  56. <link rel="stylesheet" type="text/css" href="'.kINSTALL_ASSET_LOCATION.'/main.css"/>
  57. </head>
  58. <body>
  59. <form action="" method="post">
  60. %s
  61. </form>
  62. </body>
  63. </html>';
  64. if(isset($_GET['action']) && $_GET['action'] == 'remove'){
  65. if(is_writable(__FILE__)){
  66. unlink(__FILE__);
  67. redirect(URL . '/symphony/');
  68. }
  69. render(sprintf($shell,
  70. '<h1>Update Symphony <em>Version '.kVERSION.'</em><em><a href="'.kCHANGELOG.'">change log</a></em></h1>
  71. <h2>Deletion Failed!</h2>
  72. <p>Symphony was unable to delete your <code>update.php</code> file. For security reasons, please be sure to delete the file before proceeding.</p>
  73. <br />
  74. <p>To continue to the Symphony admin, please <a href="'.URL.'/symphony/">click here</a>.</p>'
  75. ));
  76. }
  77. $settings = loadOldStyleConfig();
  78. $existing_version = $settings['symphony']['version'];
  79. if(isset($_POST['action']['update'])){
  80. $settings['symphony']['version'] = kVERSION;
  81. $settings['general']['useragent'] = 'Symphony/' . kVERSION;
  82. ## Build is no longer used
  83. unset($settings['symphony']['build']);
  84. ## Remove the old Maintenance Mode setting
  85. unset($settings['public']['maintenance_mode']);
  86. ## Set the default language
  87. if(!isset($settings['symphony']['lang'])){
  88. $settings['symphony']['lang'] = 'en';
  89. }
  90. if(writeConfig(DOCROOT . '/manifest', $settings, $settings['file']['write_mode']) === true){
  91. // build a Frontend page instance to initialise database
  92. require_once(CORE . '/class.frontend.php');
  93. $frontend = Frontend::instance();
  94. if (version_compare($existing_version, '2.0.3', '<=')) {
  95. // Add Navigation Groups
  96. if(!tableContainsField('tbl_sections', 'navigation_group')){
  97. $frontend->Database->query("ALTER TABLE `tbl_sections` ADD `navigation_group` VARCHAR( 50 ) NOT NULL DEFAULT 'Content'");
  98. $frontend->Database->query("ALTER TABLE `tbl_sections` ADD INDEX (`navigation_group`)");
  99. }
  100. // Added support for upload field to handle empty mimetypes.
  101. $upload_fields = $frontend->Database->fetch("SELECT id FROM tbl_fields WHERE `type` = 'upload'");
  102. foreach ($upload_fields as $upload_field) {
  103. $frontend->Database->query("ALTER TABLE `tbl_entries_data_{$upload_field['id']}` CHANGE `mimetype` `mimetype` VARCHAR( 50 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL");
  104. }
  105. }
  106. if (version_compare($existing_version, '2.0.4', '<=')) {
  107. $date_fields = $frontend->Database->fetch("SELECT id FROM tbl_fields WHERE `type` = 'date'");
  108. foreach ($date_fields as $field) {
  109. $frontend->Database->query("ALTER TABLE `tbl_entries_data_{$field['id']}` CHANGE `local` `local` INT(11) DEFAULT NULL;");
  110. $frontend->Database->query("ALTER TABLE `tbl_entries_data_{$field['id']}` CHANGE `gmt` `gmt` INT(11) DEFAULT NULL;");
  111. }
  112. // Update author field table to support the default value checkbox
  113. if(!tableContainsField('tbl_fields_author', 'default_to_current_user')){
  114. $frontend->Database->query("ALTER TABLE `tbl_fields_author` ADD `default_to_current_user` ENUM('yes', 'no') NOT NULL");
  115. }
  116. ## Change .htaccess from `page` to `symphony-page`
  117. $htaccess = @file_get_contents(DOCROOT . '/.htaccess');
  118. if($htaccess !== false){
  119. $htaccess = str_replace('index.php?page=$1&%{QUERY_STRING}', 'index.php?symphony-page=$1&%{QUERY_STRING}', $htaccess);
  120. @file_put_contents(DOCROOT . '/.htaccess', $htaccess);
  121. }
  122. }
  123. if (version_compare($existing_version, '2.0.5', '<=')) {
  124. ## Rebuild the .htaccess here
  125. $rewrite_base = trim(dirname($_SERVER['PHP_SELF']), DIRECTORY_SEPARATOR);
  126. if(strlen($rewrite_base) > 0){
  127. $rewrite_base .= '/';
  128. }
  129. $htaccess = '
  130. ### Symphony 2.2.x ###
  131. Options +FollowSymlinks -Indexes
  132. <IfModule mod_rewrite.c>
  133. RewriteEngine on
  134. RewriteBase /'.$rewrite_base.'
  135. ### SECURITY - Protect crucial files
  136. RewriteRule ^manifest/(.*)$ - [F]
  137. RewriteRule ^workspace/utilities/(.*).xsl$ - [F]
  138. RewriteRule ^workspace/pages/(.*).xsl$ - [F]
  139. RewriteRule ^(.*).sql$ - [F]
  140. ### DO NOT APPLY RULES WHEN REQUESTING "favicon.ico"
  141. RewriteCond %{REQUEST_FILENAME} favicon.ico [NC]
  142. RewriteRule .* - [S=14]
  143. ### IMAGE RULES
  144. RewriteRule ^image\/(.+\.(jpg|gif|jpeg|png|bmp))$ extensions/jit_image_manipulation/lib/image.php?param=$1 [L,NC]
  145. ### CHECK FOR TRAILING SLASH - Will ignore files
  146. RewriteCond %{REQUEST_FILENAME} !-f
  147. RewriteCond %{REQUEST_URI} !/$
  148. RewriteCond %{REQUEST_URI} !(.*)/$
  149. RewriteRule ^(.*)$ $1/ [L,R=301]
  150. ### URL Correction
  151. RewriteRule ^(symphony/)?index.php(/.*/?) $1$2 [NC]
  152. ### ADMIN REWRITE
  153. RewriteRule ^symphony\/?$ index.php?mode=administration&%{QUERY_STRING} [NC,L]
  154. RewriteCond %{REQUEST_FILENAME} !-d
  155. RewriteCond %{REQUEST_FILENAME} !-f
  156. RewriteRule ^symphony(\/(.*\/?))?$ index.php?symphony-page=$1&mode=administration&%{QUERY_STRING} [NC,L]
  157. ### FRONTEND REWRITE - Will ignore files and folders
  158. RewriteCond %{REQUEST_FILENAME} !-d
  159. RewriteCond %{REQUEST_FILENAME} !-f
  160. RewriteRule ^(.*\/?)$ index.php?symphony-page=$1&%{QUERY_STRING} [L]
  161. </IfModule>
  162. ######
  163. ';
  164. @file_put_contents(DOCROOT . '/.htaccess', $htaccess);
  165. // No longer need symphony/.htaccess
  166. if(file_exists(DOCROOT . '/symphony/.htaccess') && is_writable(DOCROOT . '/symphony/.htaccess')){
  167. unlink(DOCROOT . '/symphony/.htaccess');
  168. }
  169. }
  170. if(version_compare($existing_version, '2.0.6', '<=')){
  171. $frontend->Database->query('ALTER TABLE `tbl_extensions` CHANGE `version` `version` VARCHAR(20) NOT NULL');
  172. }
  173. if(version_compare($existing_version, '2.0.7RC1', '<=')){
  174. $frontend->Database->query('ALTER TABLE `tbl_authors` ADD `language` VARCHAR(15) NULL DEFAULT NULL');
  175. $settings['symphony']['pages_table_nest_children'] = 'no';
  176. writeConfig(DOCROOT . '/manifest', $settings, $settings['file']['write_mode']);
  177. }
  178. if(version_compare($existing_version, '2.0.8RC1', '<')){
  179. $frontend->Database->query('ALTER TABLE `tbl_fields_date` DROP `calendar`');
  180. }
  181. if(version_compare($existing_version, '2.0.8RC3', '<=')){
  182. ## Add -Indexes to .htaccess
  183. $htaccess = @file_get_contents(DOCROOT . '/.htaccess');
  184. if($htaccess !== false && !preg_match('/-Indexes/', $htaccess)){
  185. $htaccess = str_replace('Options +FollowSymlinks', 'Options +FollowSymlinks -Indexes', $htaccess);
  186. @file_put_contents(DOCROOT . '/.htaccess', $htaccess);
  187. }
  188. ## 2.1 uses SHA1 instead of MD5
  189. // Change the author table to allow 40 character values
  190. $frontend->Database->query(
  191. "ALTER TABLE `tbl_authors` CHANGE `password` `password` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL"
  192. );
  193. // Generate a new password for the primary author account
  194. $new_password = General::generatePassword();
  195. $username = $frontend->Database->fetchVar('username', 0,
  196. "SELECT `username` FROM `tbl_authors` WHERE `primary` = 'yes' LIMIT 1"
  197. );
  198. $frontend->Database->query(
  199. sprintf("UPDATE `tbl_authors` SET `password` = SHA1('%s') WHERE `primary` = 'yes' LIMIT 1", $new_password)
  200. );
  201. // Purge all sessions, forcing everyone to update their passwords
  202. $frontend->Database->query( "TRUNCATE TABLE `tbl_sessions`");
  203. // Update Upload field
  204. $upload_entry_tables = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_upload`");
  205. if(is_array($upload_entry_tables) && !empty($upload_entry_tables)) foreach($upload_entry_tables as $field) {
  206. $frontend->Database->query(sprintf(
  207. "ALTER TABLE `tbl_entries_data_%d` CHANGE `size` `size` INT(11) UNSIGNED NULL DEFAULT NULL",
  208. $field
  209. ));
  210. }
  211. }
  212. if(version_compare($existing_version, '2.1.0', '<=')){
  213. $frontend->Database->query(
  214. 'ALTER TABLE `tbl_fields_input` CHANGE `validator` `validator` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL;'
  215. );
  216. $frontend->Database->query(
  217. 'ALTER TABLE `tbl_fields_upload` CHANGE `validator` `validator` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL;'
  218. );
  219. $frontend->Database->query(
  220. 'ALTER TABLE `tbl_fields_taglist` CHANGE `validator` `validator` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL;'
  221. );
  222. }
  223. if(version_compare($existing_version, '2.2.0dev', '<=')){
  224. if(tableContainsField('tbl_sections_association', 'cascading_deletion')) {
  225. $frontend->Database->query(
  226. 'ALTER TABLE `tbl_sections_association` CHANGE `cascading_deletion` `hide_association` enum("yes","no") COLLATE utf8_unicode_ci NOT NULL DEFAULT "no";'
  227. );
  228. // Update Select table to include the new association field
  229. $frontend->Database->query('ALTER TABLE `tbl_fields_select` ADD `show_association` ENUM( "yes", "no" ) COLLATE utf8_unicode_ci NOT NULL DEFAULT "yes"');
  230. }
  231. if(tableContainsField('tbl_authors', 'default_section')) {
  232. // Allow Authors to be set to any area in the backend.
  233. $frontend->Database->query(
  234. 'ALTER TABLE `tbl_authors` CHANGE `default_section` `default_area` VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULL;'
  235. );
  236. }
  237. }
  238. if(version_compare($existing_version, '2.2.0', '<')){
  239. $settings['region']['datetime_separator'] = ' ';
  240. $settings['symphony']['strict_error_handling'] = 'yes';
  241. writeConfig(DOCROOT . '/manifest', $settings, $settings['file']['write_mode']);
  242. // We've added UNIQUE KEY indexes to the Author, Checkbox, Date, Input, Textarea and Upload Fields
  243. // Time to go through the entry tables and make this change as well.
  244. $author = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_author`");
  245. $checkbox = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_checkbox`");
  246. $date = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_date`");
  247. $input = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_input`");
  248. $textarea = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_textarea`");
  249. $upload = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_upload`");
  250. $field_ids = array_merge($author, $checkbox, $date, $input, $textarea, $upload);
  251. foreach($field_ids as $id) {
  252. $table = '`tbl_entries_data_' . $id . '`';
  253. try {
  254. $frontend->Database->query("ALTER TABLE " . $table . " DROP INDEX `entry_id`");
  255. }
  256. catch (Exception $ex) {}
  257. try {
  258. $frontend->Database->query("CREATE UNIQUE INDEX `entry_id` ON " . $table . " (`entry_id`)");
  259. $frontend->Database->query("OPTIMIZE TABLE " . $table);
  260. }
  261. catch (Exception $ex) {}
  262. }
  263. }
  264. if(version_compare($existing_version, '2.2.1 Beta 1', '<')) {
  265. try {
  266. $frontend->Database->query('CREATE INDEX `session_expires` ON `tbl_sessions` (`session_expires`)');
  267. $frontend->Database->query('OPTIMIZE TABLE `tbl_sessions`');
  268. }
  269. catch (Exception $ex) {}
  270. }
  271. if(version_compare($existing_version, '2.2.1 Beta 2', '<')) {
  272. // Add Security Rules from 2.2 to .htaccess
  273. try {
  274. $htaccess = file_get_contents(DOCROOT . '/.htaccess');
  275. if($htaccess !== false && !preg_match('/### SECURITY - Protect crucial files/', $htaccess)){
  276. $security = '
  277. ### SECURITY - Protect crucial files
  278. RewriteRule ^manifest/(.*)$ - [F]
  279. RewriteRule ^workspace/utilities/(.*).xsl$ - [F]
  280. RewriteRule ^workspace/pages/(.*).xsl$ - [F]
  281. RewriteRule ^(.*).sql$ - [F]
  282. RewriteRule (^|/)\. - [F]
  283. ### DO NOT APPLY RULES WHEN REQUESTING "favicon.ico"';
  284. $htaccess = str_replace('### DO NOT APPLY RULES WHEN REQUESTING "favicon.ico"', $security, $htaccess);
  285. file_put_contents(DOCROOT . '/.htaccess', $htaccess);
  286. }
  287. }
  288. catch (Exception $ex) {}
  289. // Add correct index to the `tbl_cache`
  290. try {
  291. $frontend->Database->query('ALTER TABLE `tbl_cache` DROP INDEX `creation`');
  292. $frontend->Database->query('CREATE INDEX `expiry` ON `tbl_cache` (`expiry`)');
  293. $frontend->Database->query('OPTIMIZE TABLE `tbl_cache`');
  294. }
  295. catch (Exception $ex) {}
  296. // Remove Hide Association field from Select Data tables
  297. $select_tables = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_select`");
  298. if(is_array($select_tables) && !empty($select_tables)) foreach($select_tables as $field) {
  299. if(tableContainsField('tbl_entries_data_' . $field, 'show_association')) {
  300. $frontend->Database->query(sprintf(
  301. "ALTER TABLE `tbl_entries_data_%d` DROP `show_association`",
  302. $field
  303. ));
  304. }
  305. }
  306. // Update Select table to include the sorting option
  307. if(!tableContainsField('tbl_fields_select', 'sort_options')) {
  308. $frontend->Database->query('ALTER TABLE `tbl_fields_select` ADD `sort_options` ENUM( "yes", "no" ) COLLATE utf8_unicode_ci NOT NULL DEFAULT "no"');
  309. }
  310. // Remove the 'driver' from the Config
  311. unset($settings['database']['driver']);
  312. writeConfig(DOCROOT . '/manifest', $settings, $settings['file']['write_mode']);
  313. // Remove the NOT NULL from the Author tables
  314. try {
  315. $author = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_author`");
  316. foreach($author as $id) {
  317. $table = '`tbl_entries_data_' . $id . '`';
  318. $frontend->Database->query(
  319. 'ALTER TABLE ' . $table . ' CHANGE `author_id` `author_id` int(11) unsigned NULL'
  320. );
  321. }
  322. }
  323. catch(Exception $ex) {}
  324. }
  325. if(version_compare($existing_version, '2.2.2 Beta 1', '<')) {
  326. // Rename old variations of the query_caching configuration setting
  327. if(isset($settings['database']['disable_query_caching'])) {
  328. $settings['database']['query_caching'] = ($settings['database']['disable_query_caching'] == "no") ? "on" : "off";
  329. unset($settings['database']['disable_query_caching']);
  330. }
  331. // Add Session GC collection as a configuration parameter
  332. $settings['symphony']['session_gc_divisor'] = '10';
  333. // Save the manifest changes
  334. writeConfig(DOCROOT . '/manifest', $settings, $settings['file']['write_mode']);
  335. }
  336. if(version_compare($existing_version, '2.2.2 Beta 2', '<')) {
  337. try {
  338. // Change Textareas to be MEDIUMTEXT columns
  339. $textarea_tables = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_textarea`");
  340. foreach($textarea_tables as $field) {
  341. $frontend->Database->query(sprintf(
  342. "ALTER TABLE `tbl_entries_data_%d` CHANGE `value` `value` MEDIUMTEXT, CHANGE `value_formatted` `value_formatted` MEDIUMTEXT",
  343. $field
  344. ));
  345. $frontend->Database->query(sprintf('OPTIMIZE TABLE `tbl_entries_data_%d`', $field));
  346. }
  347. }
  348. catch(Exception $ex) {}
  349. }
  350. $sbl_version = $frontend->Database->fetchVar('version', 0,
  351. "SELECT `version` FROM `tbl_extensions` WHERE `name` = 'selectbox_link_field' LIMIT 1"
  352. );
  353. $code = sprintf($shell,
  354. ' <h1>Update Symphony <em>Version '.kVERSION.'</em><em><a href="'.kCHANGELOG.'">change log</a></em></h1>
  355. <h2>Update Complete</h2>
  356. <p><strong>Post-Installation Steps: </strong></p>
  357. <br />
  358. <ol>
  359. '.
  360. (version_compare($existing_version, '2.2.1', '<') ? '
  361. <li>Version <code>2.2.1</code> introduces some improvements and fixes to Static XML Datasources. If you have any Static XML Datasources in your installation, please be sure to re-save them through the Data Source Editor to prevent unexpected results.</li>' : NULL)
  362. .
  363. (version_compare($existing_version, '2.1.0', '<') ? '
  364. <li>The password for user "<code>'.$username.'</code>" is now reset. The new temporary password is "<code>'.$new_password.'</code>". Please login and change it now.</li>' : NULL)
  365. .
  366. (file_exists(DOCROOT . '/symphony/.htaccess') ? '<li><strong>WARNING:</strong> The updater tried, but failed, to remove the file <code>symphony/.htaccess</code>. It is vitally important that this file be removed, otherwise the administration area will not function. If you have customisations to this file, you should be able to just remove the Symphony related block, but there are no guarantees.</li>' : NULL)
  367. .
  368. (version_compare($existing_version, '2.0.5', '<') ? '<li>Version <code>2.0.5</code> introduced multiple includable elements, in the Data Source Editor, for a single field. After updating from <code>2.0.5</code> or lower, the DS editor will seem to "forget" about any <code>Textarea</code> fields selected when you are editing existing Data Sources. After updating, you must ensure you re-select them before saving. <strong>Note, this will only effect Data Sources that you edit and were created prior to <code>2.0.5</code></strong>. Until that point, the field will still be included in any front-end <code>XML</code></li>' : NULL)
  369. .
  370. (version_compare($existing_version, '2.0.5', '<=') ? '<li>As of 2.0.5, Symphony comes pre-packaged with the "Debug Dev Kit" and "Profile Dev Kit" extensions, which replace the built-in functionality. Prior to using them, you must ensure the folder <code>extensions/debugdevkit/lib/bitter/caches/</code> is writable by <code>PHP</code>.</li>' : NULL)
  371. .
  372. (version_compare($existing_version, '2.0.2', '<') ? '<li>Since <code>2.0.2</code>, the built-in image manipulation features have been replaced with the <a href="http://github.com/symphonycms/jit_image_manipulation/tree/master">JIT Image Manipulation</a> extension. Should you have uploaded (or cloned) this to your Extensions folder, be sure to <a href="'.URL.'/symphony/system/extensions/">enable it.</a></li>' : NULL)
  373. .
  374. (!is_null($sbl_version) && version_compare($sbl_version, '1.22', '<') ? '<li>The "Select Box Link" field extension has been updated to 1.22, however this installation of Symphony appears to be running an older version ('.$sbl_version.'). Versions prior to 1.22 will not work correctly under Symphony <code>'.kVERSION.'</code>. The latest version can be download via the <a href="http://symphony-cms.com/download/extensions/view/20054/">Select Box Link download page</a> on the Symphony site.</li>' : NULL)
  375. .'</ol>
  376. <p>This script, <code>update.php</code>, should be removed as a safety precaution. <a href="'.URL.'/update.php?action=remove">Click here</a> to remove this file and proceed to your administration area.</p>');
  377. }
  378. else{
  379. $code = sprintf($shell,
  380. ' <h1>Update Symphony <em>Version '.kVERSION.'</em><em><a href="'.kCHANGELOG.'">change log</a></em></h1>
  381. <h2>Update Failed!</h2>
  382. <p>An error occurred while attempting to write to the Symphony configuration, <code>manifest/config.php</code>. Please check it is writable and try again.</p>
  383. <div class="submit">
  384. <input type="submit" name="action[update]" value="Update Symphony"/>
  385. </div>
  386. ');
  387. }
  388. render($code);
  389. }
  390. // Check if Symphony is already installed
  391. if(file_exists('manifest/config.php')){
  392. if(isset($settings['symphony']['version']) && version_compare(kVERSION, $settings['symphony']['version'], '<=')){
  393. $code = sprintf($shell,
  394. ' <h1>Update Symphony <em>Version '.kVERSION.'</em><em><a href="'.kCHANGELOG.'">change log</a></em></h1>
  395. <h2>Existing Installation</h2>
  396. <p>It appears that Symphony has already been installed at this location and is up to date.</p>
  397. <br />
  398. <p>This script, <code>update.php</code>, should be removed as a safety precaution. <a href="'.URL.'/update.php?action=remove">Click here</a> to remove this file and proceed to your administration area.</p>');
  399. render($code);
  400. }
  401. $code = sprintf($shell,
  402. ' <h1>Update Symphony <em>Version '.kVERSION.'</em><em><a href="'.kCHANGELOG.'">change log</a></em></h1>
  403. <h2>Update Existing Installation</h2>
  404. <p>This script will update your existing Symphony '.$settings['symphony']['version'].' installation to version '.kVERSION.'.</p>
  405. <br />
  406. '.(version_compare($existing_version, '2.1.0', '<') ? '<p><strong>Pre-Installation Notes: </strong></p>' : NULL).'
  407. <br />
  408. <ol>
  409. '.(version_compare($existing_version, '2.0.6', '<') ? '
  410. <li>As of <code>2.0.6</code>, the core <code>.htaccess</code> has changed substantially. As a result, there is no fool proof way to automatically update it. Instead, if you have any customisations to your <code>.htaccess</code>, please back up the existing copy before updating. You will then need to manually migrate the customisations to the new <code>.htaccess</code>.</li>' : NULL) .'
  411. '.(version_compare($existing_version, '2.1.0', '<') ? '
  412. <li>As of version <code>2.1</code>, the <a href="http://php.net/sha1"><code>SHA1</code></a> algorithm is used instead of MD5 for generating password data. After updating, the owner\'s login password will be reset. Please also note that all other users\' passwords will no longer be valid and will require a manual reset through Symphony\'s forgotten password feature. Alternatively, as an administrator, you can also change your users\' password on their behalf.</li>' : NULL) .'
  413. </ol>
  414. <div class="submit">
  415. <input type="submit" name="action[update]" value="Update Symphony"/>
  416. </div>');
  417. render($code);
  418. }