$text = file_get_contents("../../db/source_svn_info.txt"); if (preg_match("/\nURL: (.*?)\n/", $text, $m)) { echo "<p>Repository: <code><b>" . htmlspecialchars($m[1]) . "</b></code></p>"; } if (preg_match("/\nRevision: (.*?)\n/", $text, $m)) { echo "<p>Revision: <b>" . htmlspecialchars($m[1]) . "</b></p>"; } } ?> <h3>Built-in update system</h3> <?php if ($state->is_initialized()) { ?> <p>This is the version information used by the built-in update system. If you have <a href="http://wiki.peopleaggregator.org/Transitioning_to_Subversion_for_updates">transitioned to Subversion</a>, this information will be out of date and your version information will be down below under the "Subversion" heading.</p> <?php echo "<p>Repository: <code><b>" . htmlspecialchars($state->get_repository_root() . $state->get_repository_path()) . "</b></code></p>"; echo "<p>Revision: <b>" . htmlspecialchars($state->get_revision()) . "</b></p>"; } else { echo "<p>The built-in update system has not been initialized.</p>"; } ?> <h3>Subversion (external - .svn directory)</h3> <?php // check for .svn/entries if (file_exists("../../.svn/entries")) { echo "<p><code>.svn/entries</code> file found</p>"; $dom = new DOMDocument(); $dom->load("../../.svn/entries"); $xp = new DOMXPath($dom); $xp->registerNamespace("svn", "svn:"); foreach ($xp->query("//svn:entry[@url]") as $node) {
function main() { global $path_prefix; ?> <h1>PeopleAggregator system update</h1> <p>system update | <a href="version.php">version info</a></p> <? $tmp_dir = "$path_prefix/web/files"; $tmp_fn = "$tmp_dir/update.treediff.xml"; $state = new Subversion_PAStateStore($path_prefix); if (!$state->is_initialized()) $state->initialize(); $client = new Subversion_StandaloneClient($state, $tmp_fn); $op = @$_POST['op']; switch ($op) { case 'login': break; case 'download': echo "<h2>downloading update</h2>"; $root = $state->get_repository_root(); if (preg_match("|^https://|", $root)) { echo "<p>ERROR: attempting to update from an HTTPS update server (<code>$root</code>), but we can't do HTTPS :-(</p>"; break; } if (!preg_match("|^http://update.peopleaggregator.org/svn|", $root)) { echo '<p>WARNING: the update server is <code>'.$root.'</code>, which is not the official PeopleAggregator update server.</p>'; } elseif ($root != 'http://update.peopleaggregator.org/svn/release') { echo '<p>WARNING: updating from '.$root.', which is on the official PeopleAggregator server, but may be a test release.</p>'; } $rev = $state->get_revision(); echo '<p>Requesting an update from revision r'.$rev.' from the server (<a href="'.$root.'">root</a>, <a href="'.$root.$state->get_repository_path().'">path</a>).</p>'; $disp = new js_display(); $disp->start(); $client->displayer = $disp; $client->checkout(); $err = NULL; $f = @fopen($tmp_fn, "rt"); if ($f) { $xml = fread($f, 8192); fclose($f); if (!preg_match("|^<"."\?xml|", $xml)) { $err = "Invalid response received."; } else if (preg_match("|<m:human-readable.*?>(.*?)</m:human-readable>|s", $xml, $m)) { $err = $m[1]; } else if (preg_match('|target-revision rev="(\d+)"|s', $xml, $m)) { $target_rev = (int)$m[1]; if ($target_rev == $rev) { echo "Your system is already up to date."; unlink($tmp_fn); } } } else { $err = "Error reading temporary tree diff file $tmp_fn"; } if ($err) { echo '<div class="error">An error occurred: <b>'.htmlspecialchars($err).'</b></div>'; return; } /*<?xml version="1.0" encoding="utf-8"?> <D:error xmlns:D="DAV:" xmlns:m="http://apache.org/dav/xmlns" xmlns:C="svn:"> <C:error/> <m:human-readable errcode="160005"> Cannot replace a directory from within </m:human-readable> </D:error>*/ break; case 'test-apply': if (!file_exists($tmp_fn)) break; echo '<div id="progress-detail"><h2>Verifying that the update can be installed.</h2>'; flush(); $msg_headers = array( "localmod" => "Your local modifications conflict with the update", "perms" => "The updater is unable to access some files or directories", ); $client->displayer = new html_display(); $msg_html = ""; try { $r = $client->apply_patch(FALSE); $errors = $r['errors']; foreach ($errors as $level => $msgs) { $msg_list = ""; foreach ($msgs as $msg) { $msg_list .= "<li>".$msg."</li>"; } $msg_html .= "<h3>".$msg_headers[$level]."</h3> <ul>$msg_list</ul>"; } } catch (Subversion_Failure $e) { $msg_html = $e->getMessage(); } echo <<<EOF </div><!-- progress-detail --> <script language="javascript" type="text/javascript"><!-- // hide detail, so the user can see the error message document.getElementById("progress-detail").style.display = "none"; // --></script> EOF; if ($msg_html) { ?> <p>The update (from r<?= $state->get_revision() ?> to r<?= $client->target_revision ?>) cannot be installed cleanly for the following reason(s):</p> <div class="error"><?= $msg_html ?></div> <p>You have several options at this point if you wish to install the update:</p> <ol> <li> <p>Fix the issues listed above, then try installing the update again.</p> <? if (!@$errors['localmod']) { ?><p>HIGHLY RECOMMENDED - as the only issues above are to do with file access permissions. Please fix the permissions, and try again.</p><? } ?> <? show_op("test-apply", "Click here to try installing the update again"); ?> </li> <? if (@$errors['localmod']) { ?> <li> <p>[NOT IMPLEMENTED YET] Migrate to using Subversion for updates.</p> <p>HIGHLY RECOMMENDED if you plan to maintain local changes.</p> <? show_op("svn-migrate", "Click here to create .svn folders in your PeopleAggregator install so you can use 'svn update'", TRUE); ?> </li> <? } ?> <li> <p>Overwrite your local changes. This will probably result in a working system, but will destroy any changes you have made to your system, so make sure you know what you are doing!</p> <p>(Files with local modifications will be renamed, e.g. changedfile.php will become changedfile.php.local)</p> <? if (!@$errors['localmod']) { ?><p>NOT RECOMMENDED - as the only issues above are to do with file access permissions. Instead, please fix the permissions, and try again.</p><? } ?> <? if (@$errors['perms']) { ?><p style="font-weight: bold">CURRENTLY NOT POSSIBLE due to the access permissions errors mentioned above. Please fix them, then try again.</p><? } ?> <? show_op("force-apply", "Click here to install the update, overwriting your local changes.", @$errors['perms'] ? TRUE : FALSE); ?> </li> <li> <p>Install only the parts of the update that do not conflict with anything on your system.</p> <p>(Files with local modifications will not be touched, and new local files will block installation of new files or directories of the same name).</p> <p>This won't destroy anything you have changed, but could quite possibly result in a broken installation, so it is not recommended unless your changes are relatively minor.</p> <? if (!@$errors['localmod']) { ?><p>NOT RECOMMENDED - as the only issues above are to do with file access permissions. Instead, please fix the permissions, and try again.</p><? } ?> <? show_op("soft-apply", "Click here to install the update without overwriting/deleting anything with local changes."); ?> </li> </ol> <? } else { show_op("apply", "Confirm - apply update to your installation"); } return; // don't show 'an update has been downloaded' text case 'apply': if (!file_exists($tmp_fn)) break; echo "<h2>Applying update.</h2>"; $client->displayer = new html_display(); $client->apply_patch(TRUE); run_scripts(); return; case 'soft-apply': if (!file_exists($tmp_fn)) break; echo "<h2>Applying update without overwriting local changes.</h2>"; $client->displayer = new html_display(); $client->apply_patch("soft"); run_scripts(); return; case 'force-apply': if (!file_exists($tmp_fn)) break; echo "<h2>Apply update, overwriting local changes.</h2>"; echo "<p>Downloading extra files from the server ...</p><ul>"; // find files to download $client->displayer = new null_display(); $client->apply_patch(); $client->displayer = new html_display(); $client->download_incomplete_files($tmp_dir); echo "</ul>"; // all done - now apply the patch $client->apply_patch("force"); run_scripts(); return; default: if ($op) throw new Subversion_Failure("Invalid operation: $op"); break; } if (file_exists($tmp_fn)) { show_op("test-apply", "An update has been downloaded. Click here to apply it to your system."); } else { show_op("download", "Check for updates"); } }
function install_peopleaggregator() { global $path_prefix; ?> <h2>Detecting URLs</h2> <ul> <?php // find base url (minus http:// suffix) if (!preg_match("|^(.*?)/config/index.php\$|", $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'], $m)) { dienow("Unable to find base URL"); } $base_url_bare = $m[1]; // make sure the base url is valid if (!can_get_peepagg_txt("http://{$base_url_bare}/peopleaggregator.txt")) { dienow("Unable to guess base URL - I think it should be http://{$base_url_bare}/ but that URL does not seem to work."); } note("Good: we can access the system at http://{$base_url_bare}/"); // try stripping off the first url part (i.e. www.asdf -> asdf) $base_url_suffix = preg_replace("|^[^\\.]+\\.(.*)\$|", "\$1", $base_url_bare); $allow_spawning = FALSE; // check if it doesn't have any dots (e.g. http://colinux/web/config/) // - i.e. not suitable for sharing cookies over domains. if ($base_url_suffix == $base_url_bare) { note("Apparently running on an internal web server - not possible to run multiple networks."); } else { if (preg_match("|^\\d+\\.\\d+\\.\\d+\\.\\d+|", $base_url_bare)) { note("Running with an IP address rather than a domain name - not possible to run multiple networks."); } else { if (can_get_peepagg_txt("http://{$base_url_suffix}/peopleaggregator.txt")) { note("It looks like it is also accessible at <code>http://{$base_url_suffix}/</code>; trying <code>{$base_url_suffix}</code> as the root URL."); } else { note("It is not accessible at <code>http://{$base_url_suffix}/</code>; trying <code>{$base_url_bare}</code> as the root URL."); $base_url_suffix = $base_url_bare; } if (can_get_peepagg_txt("http://some-random-domain.{$base_url_suffix}/peopleaggregator.txt")) { note("It looks like the server is set up to host <code>*.{$base_url_suffix}</code>, so network spawning is possible."); $allow_spawning = TRUE; } else { warn("Wildcard domains do not appear to be enabled (cannot access the root of this install at http://some_random_domain.{$base_url_suffix}/) so network spawning will be disabled."); } } } global $base_url, $domain_suffix; if ($allow_spawning) { $base_url = "http://%network_name%.{$base_url_suffix}"; } else { $base_url = "http://{$base_url_bare}"; } $domain_suffix = preg_replace("|/.*\$|", "", $base_url_suffix); // stash $base_url away as config.inc will modify it $base_url_config = $base_url; note("Base URL: <code>{$base_url}</code>" . ($domain_suffix ? "; domain suffix: <code>{$domain_suffix}</code>" : "")); ?> </ul> <h2>Configuration</h2> <?php $admin_password = get_default("admin_password", ""); $admin_password2 = get_default("admin_password2", ""); $mysql_server = get_default("mysql_server", "localhost"); $mysql_dbname = get_default("mysql_dbname", "peopleaggregator"); $mysql_username = get_default("mysql_username", "peopleaggregator"); $mysql_password = get_default("mysql_password", ""); $mysql_root_username = get_default("mysql_root_username", "root"); $mysql_root_password = get_default("mysql_root_password", ""); $home_network_config = str_replace("%network_name%", "www", $base_url) . "/config/"; ?> <form method="POST" action="<?php echo $home_network_config; ?> #check"> <div class="config"> <p>Some operations (upgrading, and content administration) require an administrator password for access. Please enter an administrator password here.</p> <div class="config_item"><label for="admin_password">Admin password</label> <input type="password" id="admin_password" name="admin_password" value="<?php echo $admin_password; ?> "><?php if (!$admin_password) { echo " ← must not be blank!"; } ?> </div> <div class="config_item"><label for="admin_password">Repeat admin password</label> <input type="password" id="admin_password2" name="admin_password2" value="<?php echo $admin_password2; ?> "><?php if (!$admin_password2) { echo " ← must not be blank!"; } else { if ($admin_password != $admin_password2) { echo " ← must be the same as above!"; } } ?> </div> <p>Enter your database details below.</p> <div class="config_item"><label for="mysql_server">MySQL server</label> <input type="text" name="mysql_server" value="<?php echo $mysql_server; ?> "></div> <div class="config_item"><label for="mysql_dbname">MySQL database name</label> <input type="text" name="mysql_dbname" value="<?php echo $mysql_dbname; ?> "></div> <div class="config_item"><label for="mysql_username">MySQL username</label> <input type="text" name="mysql_username" value="<?php echo $mysql_username; ?> "></div> <div class="config_item"><label for="mysql_password">MySQL password</label> <input type="password" name="mysql_password" value="<?php echo $mysql_password; ?> "><?php if (!$mysql_password) { echo " ← must not be blank!"; } ?> </div> <p>If the database has not been created yet, you can enter your database administrator ("root") login details here to have it created automatically:</p> <div class="config_item"><label for="mysql_root_username">Administrator username</label> <input type="text" name="mysql_root_username" value="<?php echo $mysql_root_username; ?> "></div> <div class="config_item"><label for="mysql_root_password">Administrator password</label> <input type="password" name="mysql_root_password" value="<?php echo $mysql_root_password; ?> "></div> <p><input type="submit" value="Set up PeopleAggregator"></p> </div> </form> <?php // only exec the rest after someone clicks 'setup' if (!$_POST) { exit; } // wrap install process in exception handler so we can roll back $rollback_cmds = array(); try { ?> <h2 id="check">Checking config details</h2> <ul> <?php if (!$admin_password) { focus_field("admin_password"); dienow("You must supply an admin password"); } if ($admin_password != $admin_password2) { focus_field("admin_password"); dienow("Both admin paswords must be the same"); } if (!$mysql_password) { focus_field("mysql_password"); dienow("You may not use a blank password for the MySQL connection"); } $user_link = @mysql_connect($mysql_server, $mysql_username, $mysql_password); if ($user_link) { note("Able to connect to the MySQL server at {$mysql_server} with supplied login details."); // make sure the DB isn't already populated if (!mysql_select_db($mysql_dbname, $user_link)) { note("Database does not exist or is inaccessible"); mysql_close($user_link); $user_link = FALSE; } else { $sth = run_query("SHOW TABLES", $user_link); if (mysql_num_rows($sth)) { throw new Installation_Failure("The database {$mysql_dbname} already contains data. Please wipe it out or recreate the database before installing PeopleAggregator. If PeopleAggregator is already installed here, you will have to create your local_config.php file manually."); } } } else { note("Unable to connect to the MySQL server using the supplied login details"); } if (!$user_link) { note("Trying administrator login..."); $admin_link = @mysql_connect($mysql_server, $mysql_root_username, $mysql_root_password); if (!$admin_link) { dienow("Unable to connect to the MySQL server with the supplied login details or as an administrator"); } note("Able to connect to the MySQL server with the supplied administrator login details - a new database will be created."); // make sure the db doesn't already exist if (mysql_select_db($mysql_dbname, $admin_link)) { throw new Installation_Failure("Database {$mysql_dbname} already exists"); } // create it $sql = "CREATE DATABASE " . db_esc($mysql_dbname); $rollback_cmds[] = array("sql", "DROP DATABASE " . db_esc($mysql_dbname), $admin_link); run_query($sql, $admin_link); // now grant permissions with successively looser hostnames until // we find one that lets the web server access the database. foreach (array("localhost", "localhost.localdomain", $_SERVER['SERVER_NAME'], gethostbyname($_SERVER['SERVER_NAME']), "%") as $server_host) { $sql = "GRANT ALL ON " . db_esc($mysql_dbname) . ".* TO " . db_esc($mysql_username) . "@" . db_esc($server_host) . " IDENTIFIED BY '" . mysql_real_escape_string($mysql_password) . "'"; run_query($sql, $admin_link); if (($user_link = mysql_connect($mysql_server, $mysql_username, $mysql_password)) && mysql_select_db($mysql_dbname, $user_link)) { note("Successfully logged in to new database using credentials from host {$server_host}"); break; } } if (!$user_link) { throw new Installation_Failure("Failed to grant access credentials that would allow the web server to access the database. Please try creating the database manually."); } } if (!$user_link) { throw new Installation_Failure("Something went wrong - we should have successfully connected to the DB by now"); } // set all local_config.php vars global $peepagg_dsn; $peepagg_dsn = "mysql://{$mysql_username}:{$mysql_password}@{$mysql_server}/{$mysql_dbname}"; $logger_logFile = "{$path_prefix}/log/pa.log"; $default_relation_id = 1; // now write out local_config.php $local_config_text = "<" . "?php\n\n// local_config.php: This file contains server-specific settings like\n// the database password, the base URL of this installation, and\n// debugging flags. Anything in default_config.php can be overridden\n// here.\n\n// If you want to change project-specific things like the site name,\n// you can use project_config.php.\n\n// Global defaults, which are shared by all other PeopleAggregator\n// installations, are in default_config.php.\n\n// Database details.\n\$peepagg_dsn = \"{$peepagg_dsn}\";\n\n// URL to the root of the server.\n\$base_url = \"{$base_url_config}\";\n\n// Parent domain part of the URL.\n\$domain_suffix = \"{$domain_suffix}\";\n"; if ($allow_spawning) { $local_config_text .= "\n// Network operation is enabled. To disable, set \$_PA->enable_networks\n// to FALSE. To disable network spawning without deactivating existing\n// networks, set \$_PA->enable_network_spawning to FALSE.\n"; } else { $local_config_text .= "\n// Network operation disabled as wildcard domains are not configured.\n// Comment out the following line to enable network creation (after\n// configuring wildcard DNS, etc).\n\$_PA->enable_networks = FALSE;\n"; } $local_config_text .= "\n// Path to log file (you may wish to change this to /var/log/somewhere/pa.log).\n\$logger_logFile = \"\$path_prefix/log/pa.log\";\n\n// Administration password\n\$admin_password = \"{$admin_password}\";\n\n// When a new user registers on the site, they will automatically be marked as a friend of the user with this ID.\n// (The default is 1, so everyone will be a friend of the first user.)\n\$default_relation_id = {$default_relation_id};\n\n?" . ">\n"; global $config_fn; note("Writing local_config.php"); $rollback_cmds[] = array("delete", $config_fn); if (!file_put_contents($config_fn, $local_config_text)) { throw new Installation_Failure("Unable to write {$config_fn}"); } // define LOCAL_CONFIG_OVERRIDE to tell config.inc to load our new // temporary local_config.php rather than look for it in the global // location define("LOCAL_CONFIG_LOCATION_OVERRIDE", $config_fn); // now set up databases note("Initializing database ... "); run_query_file(dirname(__FILE__) . "/../../db/PeepAgg.mysql", $user_link); note("Running database upgrade script and installing default module settings ... "); try { require_once dirname(__FILE__) . "/../update/run_scripts.php"; run_update_scripts(); } catch (Exception $e) { throw new Installation_Failure("Error updating database or installing default module settings: " . $e->getMessage()); } global $do_auto_update; if (!$do_auto_update) { note("Skipping auto-upgrade preparation as it is disabled for this installation."); } else { note("Preparing system for auto-upgradeability ... "); require_once "Subversion/PAStateStore.php"; try { $store = new Subversion_PAStateStore($path_prefix); $store->initialize(); note("Subversion update root: <code>" . $store->get_repository_root() . "</code>; path: <code>" . $store->get_repository_path() . "</code>; revision: " . $store->get_revision()); } catch (Exception $e) { throw new Installation_Failure("Error preparing auto-upgrade system: " . $e->getMessage()); } } ?> </ul> <h2>All done!</h2> <p class="good">Your database has been initialized and a <code>local_config.php</code> file has been written at <code><?php echo $config_fn; ?> </code>. To finish the installation, please move this file up into the parent of the 'web' directory, then <a href="../">click here</a>.</p> <p>The following command will do this on Linux/UNIX:</p> <p style="margin-left: 5em"><code>mv <?php echo realpath($config_fn); ?> <?php echo $path_prefix; ?> /</code></p> <?php //throw new Installation_Failure("foo"); } catch (Installation_Failure $e) { warn("Installation failed (" . $e->getMessage() . ") - undoing operations"); foreach (array_reverse($rollback_cmds) as $cmd) { switch ($cmd[0]) { case 'sql': list(, $sql, $link) = $cmd; note("DB query: {$sql}"); mysql_query($sql, $link); break; case 'delete': list(, $fn) = $cmd; note("Delete: {$fn}"); unlink($fn); break; default: warn("Unknown rollback command type: " . $cmd[0]); break; } } } }