"Environment Test",
                     "description" => "The following tests have been run to determine if " .
                     "Gallery3 will work in your environment. If any of the tests have " .
                     "failed, consult the documention on http://gallery.menalto.com for " .
                     "more information on how to correct the problem.",
                     "msgs" => array());
    
    if (version_compare(PHP_VERSION, "5.2", "<")) {
      $section["msgs"]["PHP Version"] = array("error" => true,
       "text" => sprintf("Gallery3 requires PHP 5.2 or newer, current version: %s.", PHP_VERSION));
      $failed = true;
    } else {
      $section["msgs"]["PHP Version"] = array("error" => false,
        "text" => PHP_VERSION);
    }
    
    if (!(is_dir(SYSPATH) AND is_file(SYSPATH.'core/Bootstrap'.EXT))) {     
      $section["msgs"]["Kohana Directory"] = array("error" => true,
        "text" => "The configured Kohana directory does not exist or does not contain the required files.");
    } else {
      $section["msgs"]["Kohana Directory"] = array("error" => false,
        "text" => SYSPATH);
    }
                                                                       
    if (!(is_dir(APPPATH) AND is_file(APPPATH.'config/config'.EXT))) {     
      $section["msgs"]["Application Directory"] = array("error" => true,
        "text" => "The configured Gallery3 application directory does not exist or does not contain the required files.");
      $failed = true;
    } else {
      $section["msgs"]["Application Directory"] = array("error" => false,
        "text" => APPPATH);
    }
                                                                            
    if (!(is_dir(MODPATH))) {     
      $section["msgs"]["Modules Directory"] = array("error" => true,
        "text" => "The configured Gallery3 modules directory does not exist or does not contain the required files.");
      $failed = true;
    } else {
      $section["msgs"]["Modules Directory"] = array("error" => false,
        "text" => MODPATH);
    }
                                                                            
    if (!(is_dir(THEMEPATH))) {     
      $section["msgs"]["Theme Directory"] = array("error" => true,
        "text" => "The configured Gallery3 themes directory does not exist or does not contain the required files.");
      $failed = true;
    } else {
      $section["msgs"]["Themes Directory"] = array("error" => false,
        "text" => THEMEPATH);
    }
                                                                            
    if (!@preg_match("/^.$/u", utf8_encode("\xF1"))) {
      $section["msgs"]["PCRE UTF-8"] = array("error" => true,
        "text" => "Perl-Compatible Regular Expressions has not been compiled with UTF-8 support.",
        "html" => "PCRE has not been compiled with UTF-8 support.");
      $failed = true;
    } else if (!@preg_match("/^\pL$/u", utf8_encode("\xF1"))) {             
      $section["msgs"]["PCRE UTF-8"] = array("error" => true,
        "text" => "Perl-Compatible Regular Expressions has not been compiled with Unicode support.",
        "html" => "PCRE has not been compiled with Unicode property support.");
      $failed = true;
    } else {
      $section["msgs"]["PCRE UTF-8"] = array("error" => false,
        "text" => "Pass");
    }
    if (!(class_exists("ReflectionClass"))) {
      $section["msgs"]["Reflection Enabled"] = array("error" => true,
        "text" => "PHP relection is either not loaded or not compiled in.",
        "html" => "PHP relection is either not loaded or not compiled in.");
      $failed = true;
    } else {
      $section["msgs"]["Reflection Enabled"] = array("error" => false,
        "text" => "Pass");
    }
                                                                            
    if (!(function_exists("filter_list"))) {
      $section["msgs"]["Filters Enabled"] = array("error" => true,
        "text" => "The filter extension is either not loaded or not compiled in.",
        "html" => "The filter extension is either not loaded or not compiled in.");
      $failed = true;
    } else {
      $section["msgs"]["Filters Enabled"] = array("error" => false,
        "text" => "Pass");
    }
    if (!(extension_loaded("iconv"))) {
      $section["msgs"]["Iconv Loaded"] = array("error" => true,
        "text" => "The iconv extension is not loaded.",
        "html" => "The iconv extension is not loaded.");
      $failed = true;
    } else {
      $section["msgs"]["Iconv Enabled"] = array("error" => false,
        "text" => "Pass");
    }
    if (extension_loaded("mbstring") &&
        (ini_get("mbstring.func_overload") & MB_OVERLOAD_STRING)) {
      $section["msgs"]["Mbstring Overloaded"] = array("error" => true,
        "text" => "The mbstring extension is overloading PHP's native string functions.",
        "html" => "The mbstring extension is overloading PHP's native string functions.");
      $failed = true;
    } else {
      $section["msgs"]["MbString Overloaded"] = array("error" => false,
        "text" => "Pass");
    }
    if (!(isset($_SERVER["REQUEST_URI"]) || isset($_SERVER["PHP_SELF"]))) {
      $section["msgs"]["URI Determination"] = array("error" => true,
        "text" => "Neither \$_SERVER['REQUEST_URI'] or \$_SERVER['PHP_SELF'] is available.",
        "html" => "Neither \$_SERVER['REQUEST_URI'] or \$_SERVER['PHP_SELF'] is available.");
      $failed = true;
    } else {
      $section["msgs"]["URI Determination"] = array("error" => false,
        "text" => "Pass");
    }
    $short_tags = ini_get("short_open_tag");
    if (empty($short_tags)) {
      $section["msgs"]["Short Tags"] = array("error" => true,
        "text" => "Gallery3 requires that PHP short tags be enabled.",
        "html" => "Gallery3 requires that PHP short tags be enabled");
      $failed = true;
    } else {
      $section["msgs"]["Short Tags"] = array("error" => false,
        "text" => "Pass");
    }
    self::$messages[] = $section;
 
    return !$failed;
  }
  public static function display_requirements($errors=false) {
    self::$config_errors = $errors;
    if (PHP_SAPI == 'cli') {
      print self::_render("installer/views/installer.txt");
    } else {
      print self::_render("installer/views/installer.html");
    }
  }
  public static function parse_cli_parms($argv) {
    $section = array("header" => "Installation Parameters",
                     "description" => "The following parameters will be used to install and " .
                     "configure your Gallery3 installation.",
                     "msgs" => array());
    for ($i=0; $i < count($argv); $i++) {
      switch (strtolower($argv[$i])) {
      case "-d":
        $arguments["dbname"] = $argv[++$i];
        break;
      case "-h":
        $arguments["host"] = $argv[++$i];
        break;
      case "-u":
        $arguments["user"] = $argv[++$i];
        break;
      case "-p":
        $arguments["password"] = $argv[++$i];
        break;
      case "-t":
        $arguments["prefix"] = $argv[++$i];
        break;
      case "-f":
        $arguments["file"] = $argv[++$i];
        break;
      case "-i":
        $arguments["type"] = $argv[++$i];
        break;
      case "-m":
        $arguments["modules"] = $argv[++$i];
        break;
      }
    }
    $config = array("host" => "localhost", "user" => "root", "password" => "",
                    "modules" => array("core" => 1, "user" => 1), "type" => "mysqli",
                    "dbname" => "gallery3", "prefix" => "");
    if (!empty($arguments["file"])) {
      if (file_exists($arguments["file"])) {
        $save_modules = $config["modules"];
        include $arguments["file"];
        if (!is_array($config["modules"])) {
          $modules = explode(",", $config["modules"]);
          $config["modules"] = array_merge($save_modules, array_fill_keys($modules, 1));
        }
      }
      unset($arguments["file"]);
    }
    if (!empty($arguments["modules"])) {
      $modules = explode(",", $arguments["modules"]);
    
      $config["modules"] = array_merge($config["modules"], array_fill_keys($modules, 1));
      unset($arguments["modules"]);
    }                                    
    foreach (array_keys($config["modules"]) as $module) {
      unset($config["modules"][$module]);
      $config["modules"][trim($module)] = 1;
    }
    
    self::$config = array_merge($config, $arguments);
    foreach (self::$config as $key => $value) {
      if ($key == "type") {
        $value = ucfirst(self::$config["type"]);
        self::$config[$key] = $value;
        $class = "Install_{$value}_Driver";
        if (!class_exists($class)) {
          require_once(DOCROOT . "/installer/libraries/$class" . EXT);
        }
      }
      if ($key == "modules") {
        $value = implode(", ", array_keys($value));
      }
      $section["msgs"][$key] = array("text" => $value, "error" => false);
    }
    self::$messages[] = $section;
  }
  public static function check_database_authorization() {
    $section = array("header" => "Database Configuration",
                     "description" => "Gallery3 requires the following database configuration.",
                     "msgs" => array());
    $class = self::$config["type"];
    $class = "Install_{$class}_Driver";
    self::$database =
      new $class(self::$config["host"], self::$config["user"], self::$config["password"]);
    /*
     * If we got this far, then the user/password combination is valid and we can now
     * a little more information for the individual that is running the script. We can also
     * connect to the database and ask for more information
     */
    $databases = self::$database->list_dbs();
    $dbname = self::$config["dbname"];
    $db_config_valid = true;
    if (empty($databases[$dbname])) {
      $db_config_valid = false;
      $section["msgs"]["Database"] = array("text" => "Database '$dbname' is not defined",
                                           "error" => true);
    } else {
      $section["msgs"]["Database"] = array("text" => "Database '$dbname' is defined",
                                           "error" => false);
    }
    $tables = self::$database->list_tables(self::$config["dbname"]);
    $valid = count($tables) == 0;
    if (!$valid) {
      $db_config_valid = false;
      $section["msgs"]["Database Empty"] = array("text" => "Database '$dbname' is not empty",
                                           "error" => true);
    }
    
    $missing = array();
    $rights = self::$database->get_access_rights($dbname);
    foreach (array("create", "delete", "insert", "select", "update", "alter") as $priviledge) {
      if (empty($rights[$priviledge])) {
        $missing[] = $priviledge;
      }
    }
    if (!empty($missing)) {
      $db_config_valid = false;
      $section["msgs"]["Privileges"] =
        array("text" => "The following required priviledges have not been granted: " .
              implode(", ", $missing), "error" => true);
    } else {
      $section["msgs"]["Privileges"] = array("text" => "Required priviledges defined.",
                                             "error" => false);
    }
    
    self::$messages[] = $section;
    return $db_config_valid;
  }
  public static function check_docroot_writable() {
    $section = array("header" => "File System Access",
                     "description" => "The requires the following file system configuration.",
                     "msgs" => array());
    if (is_writable(DOCROOT)) {
      $writable = true;
      $section["msgs"]["Permissions"] =
        array("text" => "The installation directory '" . DOCROOT . "' is writable.",
              "error" => false);
    } else {
      $writable = false;
      $section["msgs"]["Permissions"] =
        array("text" => "The current user is unable to write to '" . DOCROOT . "'.",
              "error" => true);
    }
    self::$messages[] = $section;
    return !$writable;
  }
  
  private static function _render($view) {
    if ($view == '')
      return;
    // Buffering on
    ob_start();
    try
      {
        // Views are straight HTML pages with embedded PHP, so importing them
        // this way insures that $this can be accessed as if the user was in
        // the controller, which gives the easiest access to libraries in views
        include realpath($view . EXT);
      }
    catch (Exception $e)
      {
        // Display the exception using its internal __toString method
        echo $e;
      }
    // Fetch the output and close the buffer
    return ob_get_clean();
  }
}