From 5f7dfc272e3188fbced26a72881176c98481cfb0 Mon Sep 17 00:00:00 2001 From: Andy Staudacher Date: Tue, 9 Jun 2009 21:05:33 -0700 Subject: Remove double quotes from module.info (theme.info) attribute values. (actually, we did that before: Now removing HTML element attributes since they were delimited by single quotes because PHP's ini parser can't deal with double-quotes in values.) Background: Requiring all l10n messages a) to be well-formed HTML and b) to use double-quotes as HTML element attributes, since the l10n server side validation normalizes all attribute delimiters to double-quotes). See ticket #254. --- modules/akismet/module.info | 2 +- modules/recaptcha/module.info | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/akismet/module.info b/modules/akismet/module.info index 8655927d..d45d8a7b 100644 --- a/modules/akismet/module.info +++ b/modules/akismet/module.info @@ -1,3 +1,3 @@ name = Akismet -description = "Filter comments through the Akismet web service to detect and eliminate spam. You'll need a WordPress.com API key to use it." +description = "Filter comments through the Akismet web service to detect and eliminate spam (http://akismet.com). You'll need a WordPress.com API key to use it." version = 1 diff --git a/modules/recaptcha/module.info b/modules/recaptcha/module.info index 85397580..f2cc50cf 100644 --- a/modules/recaptcha/module.info +++ b/modules/recaptcha/module.info @@ -1,3 +1,3 @@ name = Recaptcha -description = "Recaptcha displays a graphical verification that protects the input form from abuse from 'bots,' or automated programs usually written to generate spam." +description = "Recaptcha displays a graphical verification that protects the input form from abuse from 'bots,' or automated programs usually written to generate spam (http://recaptcha.net)." version = 1 -- cgit v1.2.3 From accce788d97d19663a4c39666de03a417b5837b6 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Tue, 9 Jun 2009 21:26:28 -0700 Subject: Fix a bug in set_version() where we were always forcing the value to 1. Oops! --- modules/gallery/helpers/module.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php index 58f9b20d..dea8e22c 100644 --- a/modules/gallery/helpers/module.php +++ b/modules/gallery/helpers/module.php @@ -40,7 +40,7 @@ class module_Core { $module->name = $module_name; $module->active = $module_name == "gallery"; // only gallery is active by default } - $module->version = 1; + $module->version = $version; $module->save(); Kohana::log("debug", "$module_name: version is now $version"); } -- cgit v1.2.3 From 2fd322deeaf6b6b3f880fe21bf78664870d630a3 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Tue, 9 Jun 2009 21:26:37 -0700 Subject: ACtually implement the upgrader, and add a confirmation box when the upgrade is complete. --- modules/gallery/controllers/upgrader.php | 21 +++++++++++++ modules/gallery/views/upgrader.html.php | 54 +++++++++++++++++++++++++++----- 2 files changed, 67 insertions(+), 8 deletions(-) (limited to 'modules') diff --git a/modules/gallery/controllers/upgrader.php b/modules/gallery/controllers/upgrader.php index e8798de5..b8769b27 100644 --- a/modules/gallery/controllers/upgrader.php +++ b/modules/gallery/controllers/upgrader.php @@ -20,6 +20,27 @@ class Upgrader_Controller extends Controller { public function index() { $view = new View("upgrader.html"); + $view->available = module::available(); + $view->done = Input::instance()->get("done"); print $view; } + + public function upgrade() { + // Upgrade gallery and user first + module::install("gallery"); + module::install("user"); + + // Then upgrade the rest + foreach (module::available() as $id => $module) { + if ($id == "gallery") { + continue; + } + + if ($module->active && $module->code_version != $module->version) { + module::install($id); + } + } + + url::redirect("upgrader?done=1"); + } } diff --git a/modules/gallery/views/upgrader.html.php b/modules/gallery/views/upgrader.html.php index ecf2e265..6b9a0110 100644 --- a/modules/gallery/views/upgrader.html.php +++ b/modules/gallery/views/upgrader.html.php @@ -36,9 +36,15 @@ color: #999; font-style: italic; } + tr.current td.gallery { + color: #00d; + } tr.upgradeable td { font-weight: bold; } + tr.upgradeable td.gallery { + color: #00d; + } table { width: 600px; margin-bottom: 10px; @@ -63,28 +69,60 @@ border: 1px solid #999; background: #eee; } + div.button a { + text-decoration: none; + } div.button:hover { background: #ccc; } + div#confirmation { + position: fixed; + top: 400px; + left: 325px; + background: blue; + z-index: 1000; + margin: 10px; + text-align: center; + } + div#confirmation div { + margin: 2px; + padding: 20px; + border: 2px solid #999; + background: white; + } + .gray_on_done { + opacity: ; + }
" />
-

+ +

+
+

+

+ Gallery is up to date.", + array("url" => url::site("albums/1"))) ?> +

+
+
+ +

- + - + $module): ?> active): ?> " > -
+ name ?> @@ -100,18 +138,18 @@
-
+ -

+

-
    - +
      + active): ?>
    • name ?> -- cgit v1.2.3 From d6b808b726a20570e294e6d3eeeb8ea384979ecf Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Tue, 9 Jun 2009 21:27:55 -0700 Subject: Add security checks --- modules/gallery/controllers/upgrader.php | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'modules') diff --git a/modules/gallery/controllers/upgrader.php b/modules/gallery/controllers/upgrader.php index b8769b27..0d5bb4f6 100644 --- a/modules/gallery/controllers/upgrader.php +++ b/modules/gallery/controllers/upgrader.php @@ -19,6 +19,11 @@ */ class Upgrader_Controller extends Controller { public function index() { + // Todo: give the admin a chance to log in here + if (!user::active()->admin) { + access::forbidden(); + } + $view = new View("upgrader.html"); $view->available = module::available(); $view->done = Input::instance()->get("done"); @@ -26,6 +31,11 @@ class Upgrader_Controller extends Controller { } public function upgrade() { + // Todo: give the admin a chance to log in here + if (!user::active()->admin) { + access::forbidden(); + } + // Upgrade gallery and user first module::install("gallery"); module::install("user"); -- cgit v1.2.3 From fc64a55f2e6d2e3f16e0806e6672f7d8c8de42a7 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Wed, 10 Jun 2009 00:13:31 -0700 Subject: Golden file update --- modules/gallery/tests/xss_data.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'modules') diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt index b71262df..f47ae0dc 100644 --- a/modules/gallery/tests/xss_data.txt +++ b/modules/gallery/tests/xss_data.txt @@ -73,7 +73,7 @@ modules/gallery/views/admin_advanced_settings.html.php 25 DIRTY $var->mod modules/gallery/views/admin_advanced_settings.html.php 25 $var->name modules/gallery/views/admin_advanced_settings.html.php 27 $var->name modules/gallery/views/admin_advanced_settings.html.php 27 DIRTY $var->module_name -modules/gallery/views/admin_advanced_settings.html.php 28 $var->value +modules/gallery/views/admin_advanced_settings.html.php 29 $var->value modules/gallery/views/admin_block_log_entries.html.php 4 DIRTY $entry->severity modules/gallery/views/admin_block_log_entries.html.php 5 DIRTY $entry->user_id modules/gallery/views/admin_block_log_entries.html.php 5 $entry->user->name @@ -278,6 +278,14 @@ modules/gallery/views/simple_uploader.html.php 28 $parent-> modules/gallery/views/simple_uploader.html.php 30 $item->title modules/gallery/views/simple_uploader.html.php 77 DIRTY $item->id modules/gallery/views/simple_uploader.html.php 81 DIRTY $csrf +modules/gallery/views/upgrader.html.php 94 DIRTY $done +modules/gallery/views/upgrader.html.php 124 DIRTY $module->version +modules/gallery/views/upgrader.html.php 124 DIRTY $module->code_version +modules/gallery/views/upgrader.html.php 125 DIRTY $id +modules/gallery/views/upgrader.html.php 126 DIRTY $module->name +modules/gallery/views/upgrader.html.php 129 DIRTY $module->version +modules/gallery/views/upgrader.html.php 132 DIRTY $module->code_version +modules/gallery/views/upgrader.html.php 155 DIRTY $module->name modules/image_block/views/image_block_block.html.php 3 DIRTY $item->url() modules/image_block/views/image_block_block.html.php 4 DIRTY $item->thumb_img(array("class" => "gThumbnail")) modules/info/views/info_block.html.php 6 $item->title @@ -492,6 +500,7 @@ themes/admin_default/views/admin.html.php 20 DIRTY $theme->u themes/admin_default/views/admin.html.php 29 DIRTY $theme->url("js/jquery.dropshadow.js") themes/admin_default/views/admin.html.php 30 DIRTY $theme->url("js/ui.init.js") themes/admin_default/views/admin.html.php 31 DIRTY $theme->admin_head() +themes/admin_default/views/admin.html.php 34 DIRTY $theme->body_attributes() themes/admin_default/views/admin.html.php 35 DIRTY $theme->admin_page_top() themes/admin_default/views/admin.html.php 41 DIRTY $theme->site_status() themes/admin_default/views/admin.html.php 43 DIRTY $theme->admin_header_top() @@ -563,7 +572,6 @@ themes/default/views/header.html.php 21 DIRTY $parent-> themes/default/views/header.html.php 21 DIRTY $item->id themes/default/views/header.html.php 22 $parent->title themes/default/views/header.html.php 26 $item->title -themes/default/views/login_page.html.php 10 DIRTY $theme->url("css/screen.css") themes/default/views/movie.html.php 4 DIRTY $theme->photo_top() themes/default/views/movie.html.php 7 DIRTY $position themes/default/views/movie.html.php 7 DIRTY $sibling_count @@ -590,6 +598,7 @@ themes/default/views/page.html.php 51 DIRTY $theme->u themes/default/views/page.html.php 52 DIRTY $theme->url("js/jquery.localscroll.js") themes/default/views/page.html.php 53 DIRTY $theme->url("js/ui.init.js") themes/default/views/page.html.php 54 DIRTY $theme->head() +themes/default/views/page.html.php 57 DIRTY $theme->body_attributes() themes/default/views/page.html.php 58 DIRTY $theme->page_top() themes/default/views/page.html.php 60 DIRTY $theme->site_status() themes/default/views/page.html.php 62 DIRTY $theme->display("header.html") -- cgit v1.2.3 From 0157ed4cfe19e7a1721cbf3bf0b09db47795371f Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Wed, 10 Jun 2009 00:53:16 -0700 Subject: Update test code to match the change made in 47810c9aec1e6b190a1a90505899669a2c89b770 where we adjust the site_domain in config.php --- modules/gallery_unit_test/controllers/gallery_unit_test.php | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'modules') diff --git a/modules/gallery_unit_test/controllers/gallery_unit_test.php b/modules/gallery_unit_test/controllers/gallery_unit_test.php index 56220a19..8f3353dc 100644 --- a/modules/gallery_unit_test/controllers/gallery_unit_test.php +++ b/modules/gallery_unit_test/controllers/gallery_unit_test.php @@ -23,6 +23,13 @@ class Gallery_Unit_Test_Controller extends Controller { print Kohana::show_404(); } + // Jump through some hoops to satisfy the way that we check for the site_domain in + // config.php. We structure this such that the code in config will leave us with a + // site_domain of "." (for historical reasons) + // @todo: for tests, we should force the site_domain to something like example.com + $_SERVER["SCRIPT_FILENAME"] = "index.php"; + $_SERVER["SCRIPT_NAME"] = "./index.php"; + $original_config = DOCROOT . "var/database.php"; $test_config = VARPATH . "database.php"; if (!file_exists($original_config)) { -- cgit v1.2.3 From f20bf46868485ba17308fe8e03edcb79077f7e10 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Wed, 10 Jun 2009 01:21:57 -0700 Subject: Consider the CLI sapi the equivalent of an admin --- modules/gallery/views/kohana_error_page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules') diff --git a/modules/gallery/views/kohana_error_page.php b/modules/gallery/views/kohana_error_page.php index d9bf9698..6bf48549 100644 --- a/modules/gallery/views/kohana_error_page.php +++ b/modules/gallery/views/kohana_error_page.php @@ -59,7 +59,7 @@ - admin ?> + admin ?>

      -- cgit v1.2.3 From 73de6eedd9100bf88eed4c8d638f118485869cd3 Mon Sep 17 00:00:00 2001 From: Bharat Mediratta Date: Wed, 10 Jun 2009 01:23:18 -0700 Subject: Rename package -> packager (it's a noun which has verbs on it). Force a HTTP_HOST so that url::base() works. --- modules/gallery/controllers/package.php | 169 ------------------------------ modules/gallery/controllers/packager.php | 171 +++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 169 deletions(-) delete mode 100644 modules/gallery/controllers/package.php create mode 100644 modules/gallery/controllers/packager.php (limited to 'modules') diff --git a/modules/gallery/controllers/package.php b/modules/gallery/controllers/package.php deleted file mode 100644 index f5146fc8..00000000 --- a/modules/gallery/controllers/package.php +++ /dev/null @@ -1,169 +0,0 @@ -_reset(); // empty and reinstall the standard modules - $this->_dump_database(); // Dump the database - $this->_dump_var(); // Dump the var directory - } catch (Exception $e) { - print $e->getTraceAsString(); - return; - } - - print "Successfully wrote install.sql and init_var.php\n"; - } - - private function _reset() { - $db = Database::instance(); - - // Drop all tables - foreach ($db->list_tables() as $table) { - $db->query("DROP TABLE IF EXISTS `$table`"); - } - - // Clean out data - dir::unlink(VARPATH . "uploads"); - dir::unlink(VARPATH . "albums"); - dir::unlink(VARPATH . "resizes"); - dir::unlink(VARPATH . "thumbs"); - dir::unlink(VARPATH . "modules"); - dir::unlink(VARPATH . "tmp"); - - $db->clear_cache(); - module::$modules = array(); - module::$active = array(); - - // Use a known random seed so that subsequent packaging runs will reuse the same random - // numbers, keeping our install.sql file more stable. - srand(0); - - gallery_installer::install(true); - module::load_modules(); - - foreach (array("user", "comment", "organize", "info", "rss", - "search", "slideshow", "tag") as $module_name) { - module::install($module_name); - module::activate($module_name); - } - } - - private function _dump_database() { - // We now have a clean install with just the packages that we want. Make sure that the - // database is clean too. - $i = 1; - foreach (array("blocks_dashboard_sidebar", "blocks_dashboard_center") as $key) { - $blocks = array(); - foreach (unserialize(module::get_var("gallery", $key)) as $rnd => $value) { - $blocks[++$i] = $value; - } - module::set_var("gallery", $key, serialize($blocks)); - } - - $db = Database::instance(); - $db->query("TRUNCATE {sessions}"); - $db->query("TRUNCATE {logs}"); - $db->query("DELETE FROM {vars} WHERE `module_name` = 'core' AND `name` = '_cache'"); - $db->update("users", array("password" => ""), array("id" => 1)); - $db->update("users", array("password" => ""), array("id" => 2)); - - $dbconfig = Kohana::config('database.default'); - $conn = $dbconfig["connection"]; - $pass = $conn["pass"] ? "-p{$conn['pass']}" : ""; - $sql_file = DOCROOT . "installer/install.sql"; - if (!is_writable($sql_file)) { - print "$sql_file is not writeable"; - return; - } - $command = "mysqldump --compact --add-drop-table -h{$conn['host']} " . - "-u{$conn['user']} $pass {$conn['database']} > $sql_file"; - exec($command, $output, $status); - if ($status) { - print "
      ";
      -      print "$command\n";
      -      print "Failed to dump database\n";
      -      print implode("\n", $output);
      -      return;
      -    }
      -
      -    // Post-process the sql file
      -    $buf = "";
      -    $root = ORM::factory("item", 1);
      -    $root_created_timestamp = $root->created;
      -    $root_updated_timestamp = $root->updated;
      -    foreach (file($sql_file) as $line) {
      -      // Prefix tables
      -      $line = preg_replace(
      -        "/(CREATE TABLE|IF EXISTS|INSERT INTO) `{$dbconfig['table_prefix']}(\w+)`/", "\\1 {\\2}",
      -        $line);
      -
      -      // Normalize dates
      -      $line = preg_replace("/,$root_created_timestamp,/", ",UNIX_TIMESTAMP(),", $line);
      -      $line = preg_replace("/,$root_updated_timestamp,/", ",UNIX_TIMESTAMP(),", $line);
      -      $buf .= $line;
      -    }
      -    $fd = fopen($sql_file, "wb");
      -    fwrite($fd, $buf);
      -    fclose($fd);
      -  }
      -
      -  private function _dump_var() {
      -    $objects = new RecursiveIteratorIterator(
      -      new RecursiveDirectoryIterator(VARPATH),
      -      RecursiveIteratorIterator::SELF_FIRST);
      -
      -    $var_file = DOCROOT . "installer/init_var.php";
      -    if (!is_writable($var_file)) {
      -      print "$var_file is not writeable";
      -      return;
      -    }
      -
      -    $paths = array();
      -    foreach($objects as $name => $file){
      -      if ($file->getBasename() == "database.php") {
      -        continue;
      -      } else if (basename($file->getPath()) == "logs") {
      -        continue;
      -      }
      -
      -      if ($file->isDir()) {
      -        $paths[] = "VARPATH . \"" . substr($name, strlen(VARPATH)) . "\"";
      -      } else {
      -        // @todo: serialize non-directories
      -        print "Unknown file: $name";
      -        return;
      -      }
      -    }
      -    // Sort the paths so that the var file is stable
      -    sort($paths);
      -
      -    $fd = fopen($var_file, "w");
      -    fwrite($fd, "\n");
      -    fwrite($fd, "_reset();                // empty and reinstall the standard modules
      +      $this->_dump_database();        // Dump the database
      +      $this->_dump_var();             // Dump the var directory
      +    } catch (Exception $e) {
      +      print $e->getTraceAsString();
      +      return;
      +    }
      +
      +    print "Successfully wrote install.sql and init_var.php\n";
      +  }
      +
      +  private function _reset() {
      +    $db = Database::instance();
      +
      +    // Drop all tables
      +    foreach ($db->list_tables() as $table) {
      +      $db->query("DROP TABLE IF EXISTS `$table`");
      +    }
      +
      +    // Clean out data
      +    dir::unlink(VARPATH . "uploads");
      +    dir::unlink(VARPATH . "albums");
      +    dir::unlink(VARPATH . "resizes");
      +    dir::unlink(VARPATH . "thumbs");
      +    dir::unlink(VARPATH . "modules");
      +    dir::unlink(VARPATH . "tmp");
      +
      +    $db->clear_cache();
      +    module::$modules = array();
      +    module::$active = array();
      +
      +    // Use a known random seed so that subsequent packaging runs will reuse the same random
      +    // numbers, keeping our install.sql file more stable.
      +    srand(0);
      +
      +    gallery_installer::install(true);
      +    module::load_modules();
      +
      +    foreach (array("user", "comment", "organize", "info", "rss",
      +                   "search", "slideshow", "tag") as $module_name) {
      +      module::install($module_name);
      +      module::activate($module_name);
      +    }
      +  }
      +
      +  private function _dump_database() {
      +    // We now have a clean install with just the packages that we want.  Make sure that the
      +    // database is clean too.
      +    $i = 1;
      +    foreach (array("blocks_dashboard_sidebar", "blocks_dashboard_center") as $key) {
      +      $blocks = array();
      +      foreach (unserialize(module::get_var("gallery", $key)) as $rnd => $value) {
      +        $blocks[++$i] = $value;
      +      }
      +      module::set_var("gallery", $key, serialize($blocks));
      +    }
      +
      +    $db = Database::instance();
      +    $db->query("TRUNCATE {sessions}");
      +    $db->query("TRUNCATE {logs}");
      +    $db->query("DELETE FROM {vars} WHERE `module_name` = 'core' AND `name` = '_cache'");
      +    $db->update("users", array("password" => ""), array("id" => 1));
      +    $db->update("users", array("password" => ""), array("id" => 2));
      +
      +    $dbconfig = Kohana::config('database.default');
      +    $conn = $dbconfig["connection"];
      +    $pass = $conn["pass"] ? "-p{$conn['pass']}" : "";
      +    $sql_file = DOCROOT . "installer/install.sql";
      +    if (!is_writable($sql_file)) {
      +      print "$sql_file is not writeable";
      +      return;
      +    }
      +    $command = "mysqldump --compact --add-drop-table -h{$conn['host']} " .
      +      "-u{$conn['user']} $pass {$conn['database']} > $sql_file";
      +    exec($command, $output, $status);
      +    if ($status) {
      +      print "
      ";
      +      print "$command\n";
      +      print "Failed to dump database\n";
      +      print implode("\n", $output);
      +      return;
      +    }
      +
      +    // Post-process the sql file
      +    $buf = "";
      +    $root = ORM::factory("item", 1);
      +    $root_created_timestamp = $root->created;
      +    $root_updated_timestamp = $root->updated;
      +    foreach (file($sql_file) as $line) {
      +      // Prefix tables
      +      $line = preg_replace(
      +        "/(CREATE TABLE|IF EXISTS|INSERT INTO) `{$dbconfig['table_prefix']}(\w+)`/", "\\1 {\\2}",
      +        $line);
      +
      +      // Normalize dates
      +      $line = preg_replace("/,$root_created_timestamp,/", ",UNIX_TIMESTAMP(),", $line);
      +      $line = preg_replace("/,$root_updated_timestamp,/", ",UNIX_TIMESTAMP(),", $line);
      +      $buf .= $line;
      +    }
      +    $fd = fopen($sql_file, "wb");
      +    fwrite($fd, $buf);
      +    fclose($fd);
      +  }
      +
      +  private function _dump_var() {
      +    $objects = new RecursiveIteratorIterator(
      +      new RecursiveDirectoryIterator(VARPATH),
      +      RecursiveIteratorIterator::SELF_FIRST);
      +
      +    $var_file = DOCROOT . "installer/init_var.php";
      +    if (!is_writable($var_file)) {
      +      print "$var_file is not writeable";
      +      return;
      +    }
      +
      +    $paths = array();
      +    foreach($objects as $name => $file){
      +      if ($file->getBasename() == "database.php") {
      +        continue;
      +      } else if (basename($file->getPath()) == "logs") {
      +        continue;
      +      }
      +
      +      if ($file->isDir()) {
      +        $paths[] = "VARPATH . \"" . substr($name, strlen(VARPATH)) . "\"";
      +      } else {
      +        // @todo: serialize non-directories
      +        print "Unknown file: $name";
      +        return;
      +      }
      +    }
      +    // Sort the paths so that the var file is stable
      +    sort($paths);
      +
      +    $fd = fopen($var_file, "w");
      +    fwrite($fd, "\n");
      +    fwrite($fd, "
      Date: Wed, 10 Jun 2009 01:23:44 -0700
      Subject: Add CLI sapi support
      
      ---
       modules/gallery/controllers/upgrader.php | 12 ++++++++++--
       1 file changed, 10 insertions(+), 2 deletions(-)
      
      (limited to 'modules')
      
      diff --git a/modules/gallery/controllers/upgrader.php b/modules/gallery/controllers/upgrader.php
      index 0d5bb4f6..0833e253 100644
      --- a/modules/gallery/controllers/upgrader.php
      +++ b/modules/gallery/controllers/upgrader.php
      @@ -32,7 +32,11 @@ class Upgrader_Controller extends Controller {
       
         public function upgrade() {
           // Todo: give the admin a chance to log in here
      -    if (!user::active()->admin) {
      +    if (php_sapi_name() == "cli") {
      +      // @todo this may screw up some module installers, but we don't have a better answer at
      +      // this time.
      +      $_SERVER["HTTP_HOST"] = "example.com";
      +    } else if (!user::active()->admin) {
             access::forbidden();
           }
       
      @@ -51,6 +55,10 @@ class Upgrader_Controller extends Controller {
             }
           }
       
      -    url::redirect("upgrader?done=1");
      +    if (php_sapi_name() == "cli") {
      +      print "Upgrade complete\n";
      +    } else {
      +      url::redirect("upgrader?done=1");
      +    }
         }
       }
      -- 
      cgit v1.2.3