install.php
changeset 200 07cf7b0c175f
parent 199 c15c1d2bdeb8
child 201 c26308d81882
equal deleted inserted replaced
199:c15c1d2bdeb8 200:07cf7b0c175f
    62 require('includes/constants.php');
    62 require('includes/constants.php');
    63 require('includes/rijndael.php');
    63 require('includes/rijndael.php');
    64 require('includes/functions.php');
    64 require('includes/functions.php');
    65 
    65 
    66 strip_magic_quotes_gpc();
    66 strip_magic_quotes_gpc();
       
    67 $neutral_color = 'C';
       
    68 
       
    69 //
       
    70 // INSTALLER LIBRARY
       
    71 //
       
    72 
       
    73 function run_installer_stage($stage_id, $stage_name, $function, $failure_explanation, $allow_skip = true)
       
    74 {
       
    75   static $resumed = false;
       
    76   static $resume_stack = array();
       
    77   
       
    78   if ( empty($resume_stack) && isset($_POST['resume_stack']) && preg_match('/[a-z_]+((\|[a-z_]+)+)/', $_POST['resume_stack']) )
       
    79   {
       
    80     $resume_stack = explode('|', $_POST['resume_stack']);
       
    81   }
       
    82   
       
    83   $already_run = false;
       
    84   if ( in_array($stage_id, $resume_stack) )
       
    85   {
       
    86     $already_run = true;
       
    87   }
       
    88   
       
    89   if ( !$resumed )
       
    90   {
       
    91     if ( !isset($_GET['stage']) )
       
    92       $resumed = true;
       
    93     if ( isset($_GET['stage']) && $_GET['stage'] == $stage_id )
       
    94     {
       
    95       $resumed = true;
       
    96     }
       
    97   }
       
    98   if ( !$resumed && $allow_skip )
       
    99   {
       
   100     echo_stage_success($stage_id, "[dbg: skipped] $stage_name");
       
   101     return false;
       
   102   }
       
   103   if ( !function_exists($function) )
       
   104     die('libenanoinstall: CRITICAL: function "' . $function . '" for ' . $stage_id . ' doesn\'t exist');
       
   105   $result = @call_user_func($function, false, $already_run);
       
   106   if ( $result )
       
   107   {
       
   108     echo_stage_success($stage_id, $stage_name);
       
   109     $resume_stack[] = $stage_id;
       
   110     return true;
       
   111   }
       
   112   else
       
   113   {
       
   114     echo_stage_failure($stage_id, $stage_name, $failure_explanation, $resume_stack);
       
   115     return false;
       
   116   }
       
   117 }
       
   118 
       
   119 function start_install_table()
       
   120 {
       
   121   echo '<table border="0" cellspacing="0" cellpadding="0">' . "\n";
       
   122 }
       
   123 
       
   124 function close_install_table()
       
   125 {
       
   126   echo '</table>' . "\n\n";
       
   127 }
       
   128 
       
   129 function echo_stage_success($stage_id, $stage_name)
       
   130 {
       
   131   global $neutral_color;
       
   132   $neutral_color = ( $neutral_color == 'A' ) ? 'C' : 'A';
       
   133   ob_start();
       
   134   echo '<tr><td style="width: 500px; background-color: #' . "{$neutral_color}{$neutral_color}FF{$neutral_color}{$neutral_color}" . '; padding: 0 5px;">' . htmlspecialchars($stage_name) . '</td><td style="padding: 0 5px;"><img alt="Done" src="images/good.gif" /></td></tr>' . "\n";
       
   135   ob_end_flush();
       
   136 }
       
   137 
       
   138 function echo_stage_failure($stage_id, $stage_name, $failure_explanation, $resume_stack)
       
   139 {
       
   140   global $neutral_color;
       
   141   
       
   142   $neutral_color = ( $neutral_color == 'A' ) ? 'C' : 'A';
       
   143   ob_start();
       
   144   echo '<tr><td style="width: 500px; background-color: #' . "FF{$neutral_color}{$neutral_color}{$neutral_color}{$neutral_color}" . '; padding: 0 5px;">' . htmlspecialchars($stage_name) . '</td><td style="padding: 0 5px;"><img alt="Failed" src="images/bad.gif" /></td></tr>' . "\n";
       
   145   ob_end_flush();
       
   146   close_install_table();
       
   147   $post_data = '';
       
   148   foreach ( $_POST as $key => $value )
       
   149   {
       
   150     $value = htmlspecialchars($value);
       
   151     $key = htmlspecialchars($key);
       
   152     $post_data .= "          <input type=\"hidden\" name=\"$key\" value=\"$value\" />\n";
       
   153   }
       
   154   echo '<form action="install.php?mode=install&amp;stage=' . $stage_id . '" method="post">
       
   155           ' . $post_data . '
       
   156           <input type="hidden" name="resume_stack" value="' . htmlspecialchars(implode('|', $resume_stack)) . '" />
       
   157           <h3>Enano installation failed.</h3>
       
   158            <p>' . $failure_explanation . '</p>
       
   159            <p>When you have corrected the error, click the button below to attempt to continue the installation.</p>
       
   160            <p style="text-align: center;"><input type="submit" value="Retry installation" /></p>
       
   161         </form>';
       
   162   global $template, $template_bak;
       
   163   if ( is_object($template_bak) )
       
   164     $template_bak->footer();
       
   165   else
       
   166     $template->footer();
       
   167   exit;
       
   168 }
       
   169 
       
   170 //
       
   171 // INSTALLER STAGES
       
   172 //
       
   173 
       
   174 function stg_mysql_connect($act_get = false)
       
   175 {
       
   176   static $conn = false;
       
   177   if ( $act_get )
       
   178     return $conn;
       
   179   
       
   180   $db_user = mysql_real_escape_string($_POST['db_user']);
       
   181   $db_pass = mysql_real_escape_string($_POST['db_pass']);
       
   182   $db_name = mysql_real_escape_string($_POST['db_name']);
       
   183   
       
   184   if ( !preg_match('/^[a-z0-9_]+$/', $db_name) )
       
   185     die("<p>SECURITY: malformed database name</p>");
       
   186   
       
   187   // First, try to connect using the normal credentials
       
   188   $conn = @mysql_connect($_POST['db_host'], $_POST['db_user'], $_POST['db_pass']);
       
   189   if ( !$conn )
       
   190   {
       
   191     // Connection failed. Do we have the root username and password?
       
   192     if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) )
       
   193     {
       
   194       $conn_root = @mysql_connect($_POST['db_host'], $_POST['db_root_user'], $_POST['db_root_pass']);
       
   195       if ( !$conn_root )
       
   196       {
       
   197         // Couldn't connect using either set of credentials. Bail out.
       
   198         return false;
       
   199       }
       
   200       // Create the user account
       
   201       $q = @mysql_query("GRANT ALL PRIVILEGES ON test.* TO '{$db_user}'@'localhost' IDENTIFIED BY '$db_pass' WITH GRANT OPTION;", $conn);
       
   202       if ( !$q )
       
   203         return false;
       
   204       // Revoke privileges from test, we don't need them
       
   205       $q = @mysql_query("REVOKE ALL PRIVILEGES ON test.* FROM '{$db_user}'@'localhost';", $conn);
       
   206       if ( !$q )
       
   207         return false;
       
   208       if ( $_POST['db_host'] != 'localhost' && $_POST['db_host'] != '127.0.0.1' && $_POST['db_host'] != '::1' )
       
   209       {
       
   210         // If not connecting to a server running on localhost, allow from any host
       
   211         // this is safer than trying to detect the hostname of the webserver, but less secure
       
   212         $q = @mysql_query("GRANT ALL PRIVILEGES ON test.* TO '{$db_user}'@'%' IDENTIFIED BY '$db_pass' WITH GRANT OPTION;", $conn);
       
   213         if ( !$q )
       
   214           return false;
       
   215         // Revoke privileges from test, we don't need them
       
   216         $q = @mysql_query("REVOKE ALL PRIVILEGES ON test.* FROM '{$db_user}'@'%';", $conn);
       
   217         if ( !$q )
       
   218           return false;
       
   219       }
       
   220     }
       
   221   }
       
   222   $q = @mysql_query("USE $db_name;", $conn);
       
   223   if ( !$q )
       
   224   {
       
   225     // access denied to the database; try the whole root schenanegan again
       
   226     if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) )
       
   227     {
       
   228       $conn_root = @mysql_connect($_POST['db_host'], $_POST['db_root_user'], $_POST['db_root_pass']);
       
   229       if ( !$conn_root )
       
   230       {
       
   231         // Couldn't connect as root; bail out
       
   232         return false;
       
   233       }
       
   234       // create the database, if it doesn't exist
       
   235       $q = @mysql_query("CREATE DATABASE $db_name;", $conn);
       
   236       if ( !$q )
       
   237         // this really should never fail, so don't give any tolerance to it
       
   238         return false;
       
   239       // we're in with root rights; grant access to the database
       
   240       $q = @mysql_query("GRANT ALL PRIVILEGES ON $db_name.* TO '{$db_user}'@'localhost';", $conn);
       
   241       if ( !$q )
       
   242         return false;
       
   243       if ( $_POST['db_host'] != 'localhost' && $_POST['db_host'] != '127.0.0.1' && $_POST['db_host'] != '::1' )
       
   244       {
       
   245         $q = @mysql_query("GRANT ALL PRIVILEGES ON $db_name.* TO '{$db_user}'@'%';", $conn);
       
   246         if ( !$q )
       
   247           return false;
       
   248       }
       
   249     }
       
   250     else
       
   251     {
       
   252       return false;
       
   253     }
       
   254     // try again
       
   255     $q = @mysql_query("USE '$db_name';", $conn);
       
   256     if ( !$q )
       
   257       // really failed this time; bail out
       
   258       return false;
       
   259   }
       
   260   // connected and database exists
       
   261   return true;
       
   262 }
       
   263 
       
   264 function stg_drop_tables()
       
   265 {
       
   266   $conn = stg_mysql_connect(true);
       
   267   if ( !$conn )
       
   268     return false;
       
   269   // Our list of tables included in Enano
       
   270   $tables = Array( 'categories', 'comments', 'config', 'logs', 'page_text', 'session_keys', 'pages', 'users', 'users_extra', 'themes', 'buddies', 'banlist', 'files', 'privmsgs', 'sidebar', 'hits', 'search_index', 'groups', 'group_members', 'acl', 'search_cache', 'tags', 'page_groups', 'page_group_members' );
       
   271   
       
   272   // Drop each table individually; if it fails, it probably means we're trying to drop a
       
   273   // table that didn't exist in the Enano version we're deleting the database for.
       
   274   foreach ( $tables as $table )
       
   275   {
       
   276     // Remember that table_prefix is sanitized.
       
   277     $table = "{$_POST['table_prefix']}$table";
       
   278     @mysql_query("DROP TABLE $table;", $conn);
       
   279   }
       
   280   return true;
       
   281 }
       
   282 
       
   283 function stg_decrypt_admin_pass($act_get = false)
       
   284 {
       
   285   static $decrypted_pass = false;
       
   286   if ( $act_get )
       
   287     return $decrypted_pass;
       
   288   
       
   289   $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
       
   290   
       
   291   if ( !empty($_POST['crypt_data']) )
       
   292   {
       
   293     require('config.new.php');
       
   294     if ( !isset($cryptkey) )
       
   295     {
       
   296       return false;
       
   297     }
       
   298     define('_INSTRESUME_AES_KEYBACKUP', $key);
       
   299     $key = hexdecode($cryptkey);
       
   300     
       
   301     $decrypted_pass = $aes->decrypt($_POST['crypt_data'], $key, ENC_HEX);
       
   302     
       
   303   }
       
   304   else
       
   305   {
       
   306     $decrypted_pass = $_POST['admin_pass'];
       
   307   }
       
   308   if ( empty($decrypted_pass) )
       
   309     return false;
       
   310   return true;
       
   311 }
       
   312 
       
   313 function stg_generate_aes_key($act_get = false)
       
   314 {
       
   315   static $key = false;
       
   316   if ( $act_get )
       
   317     return $key;
       
   318   
       
   319   $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
       
   320   $key = $aes->gen_readymade_key();
       
   321   return true;
       
   322 }
       
   323 
       
   324 function stg_parse_schema($act_get = false)
       
   325 {
       
   326   static $schema;
       
   327   if ( $act_get )
       
   328     return $schema;
       
   329   
       
   330   $admin_pass = stg_decrypt_admin_pass(true);
       
   331   $key = stg_generate_aes_key(true);
       
   332   $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
       
   333   $key = $aes->hextostring($key);
       
   334   $admin_pass = $aes->encrypt($admin_pass, $key, ENC_HEX);
       
   335   
       
   336   $cacheonoff = is_writable(ENANO_ROOT.'/cache/') ? '1' : '0';
       
   337   
       
   338   $schema = file_get_contents('schema.sql');
       
   339   $schema = str_replace('{{SITE_NAME}}',    mysql_real_escape_string($_POST['sitename']   ), $schema);
       
   340   $schema = str_replace('{{SITE_DESC}}',    mysql_real_escape_string($_POST['sitedesc']   ), $schema);
       
   341   $schema = str_replace('{{COPYRIGHT}}',    mysql_real_escape_string($_POST['copyright']  ), $schema);
       
   342   $schema = str_replace('{{ADMIN_USER}}',   mysql_real_escape_string($_POST['admin_user'] ), $schema);
       
   343   $schema = str_replace('{{ADMIN_PASS}}',   mysql_real_escape_string($admin_pass          ), $schema);
       
   344   $schema = str_replace('{{ADMIN_EMAIL}}',  mysql_real_escape_string($_POST['admin_email']), $schema);
       
   345   $schema = str_replace('{{ENABLE_CACHE}}', mysql_real_escape_string($cacheonoff          ), $schema);
       
   346   $schema = str_replace('{{REAL_NAME}}',    '',                                              $schema);
       
   347   $schema = str_replace('{{TABLE_PREFIX}}', $_POST['table_prefix'],                          $schema);
       
   348   $schema = str_replace('{{VERSION}}',      ENANO_VERSION,                                   $schema);
       
   349   $schema = str_replace('{{ADMIN_EMBED_PHP}}', $_POST['admin_embed_php'],                    $schema);
       
   350   // Not anymore!! :-D
       
   351   // $schema = str_replace('{{BETA_VERSION}}', ENANO_BETA_VERSION,                              $schema);
       
   352   
       
   353   if(isset($_POST['wiki_mode']))
       
   354   {
       
   355     $schema = str_replace('{{WIKI_MODE}}', '1', $schema);
       
   356   }
       
   357   else
       
   358   {
       
   359     $schema = str_replace('{{WIKI_MODE}}', '0', $schema);
       
   360   }
       
   361   
       
   362   // Build an array of queries      
       
   363   $schema = explode("\n", $schema);
       
   364   
       
   365   foreach ( $schema as $i => $sql )
       
   366   {
       
   367     $query =& $schema[$i];
       
   368     $t = trim($query);
       
   369     if ( empty($t) || preg_match('/^(\#|--)/i', $t) )
       
   370     {
       
   371       unset($schema[$i]);
       
   372       unset($query);
       
   373     }
       
   374   }
       
   375   
       
   376   $schema = array_values($schema);
       
   377   $schema = implode("\n", $schema);
       
   378   $schema = explode(";\n", $schema);
       
   379   
       
   380   foreach ( $schema as $i => $sql )
       
   381   {
       
   382     $query =& $schema[$i];
       
   383     if ( substr($query, ( strlen($query) - 1 ), 1 ) != ';' )
       
   384     {
       
   385       $query .= ';';
       
   386     }
       
   387   }
       
   388   
       
   389   return true;
       
   390 }
       
   391 
       
   392 function stg_install($_unused, $already_run)
       
   393 {
       
   394   // This one's pretty easy.
       
   395   $conn = stg_mysql_connect(true);
       
   396   if ( !is_resource($conn) )
       
   397     return false;
       
   398   $schema = stg_parse_schema(true);
       
   399   if ( !is_array($schema) )
       
   400     return false;
       
   401   
       
   402   // If we're resuming installation, the encryption key was regenerated.
       
   403   // This means we'll have to update the encrypted password in the database.
       
   404   if ( $already_run )
       
   405   {
       
   406     $admin_pass = stg_decrypt_admin_pass(true);
       
   407     $key = stg_generate_aes_key(true);
       
   408     $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
       
   409     $key = $aes->hextostring($key);
       
   410     $admin_pass = $aes->encrypt($admin_pass, $key, ENC_HEX);
       
   411     $admin_user = mysql_real_escape_string($_POST['admin_user']);
       
   412     
       
   413     $q = @mysql_query("UPDATE {$_POST['table_prefix']}users SET password='$admin_pass' WHERE username='$admin_user';");
       
   414     if ( !$q )
       
   415     {
       
   416       echo '<p><tt>MySQL return: ' . mysql_error() . '</tt></p>';
       
   417       return false;
       
   418     }
       
   419     
       
   420     return true;
       
   421   }
       
   422   
       
   423   // OK, do the loop, baby!!!
       
   424   foreach($schema as $q)
       
   425   {
       
   426     $r = mysql_query($q, $conn);
       
   427     if ( !$r )
       
   428     {
       
   429       echo '<p><tt>MySQL return: ' . mysql_error() . '</tt></p>';
       
   430       return false;
       
   431     }
       
   432   }
       
   433   
       
   434   return true;
       
   435 }
       
   436 
       
   437 function stg_write_config()
       
   438 {
       
   439   $privkey = stg_generate_aes_key(true);
       
   440   
       
   441   switch($_POST['urlscheme'])
       
   442   {
       
   443     case "ugly":
       
   444     default:
       
   445       $cp = scriptPath.'/index.php?title=';
       
   446       break;
       
   447     case "short":
       
   448       $cp = scriptPath.'/index.php/';
       
   449       break;
       
   450     case "tiny":
       
   451       $cp = scriptPath.'/';
       
   452       break;
       
   453   }
       
   454   
       
   455   if ( $_POST['urlscheme'] == 'tiny' )
       
   456   {
       
   457     $contents = '# Begin Enano rules
       
   458 RewriteEngine on
       
   459 RewriteCond %{REQUEST_FILENAME} !-d
       
   460 RewriteCond %{REQUEST_FILENAME} !-f
       
   461 RewriteRule ^(.+) '.scriptPath.'/index.php?title=$1 [L,QSA]
       
   462 RewriteRule \.(php|html|gif|jpg|png|css|js)$ - [L]
       
   463 # End Enano rules
       
   464 ';
       
   465     if ( file_exists('./.htaccess') )
       
   466       $ht = fopen(ENANO_ROOT.'/.htaccess', 'a+');
       
   467     else
       
   468       $ht = fopen(ENANO_ROOT.'/.htaccess.new', 'w');
       
   469     if ( !$ht )
       
   470       return false;
       
   471     fwrite($ht, $contents);
       
   472     fclose($ht);
       
   473   }
       
   474 
       
   475   $config_file = '<?php
       
   476 /* Enano auto-generated configuration file - editing not recommended! */
       
   477 $dbhost   = \''.addslashes($_POST['db_host']).'\';
       
   478 $dbname   = \''.addslashes($_POST['db_name']).'\';
       
   479 $dbuser   = \''.addslashes($_POST['db_user']).'\';
       
   480 $dbpasswd = \''.addslashes($_POST['db_pass']).'\';
       
   481 if ( !defined(\'ENANO_CONSTANTS\') )
       
   482 {
       
   483 define(\'ENANO_CONSTANTS\', \'\');
       
   484 define(\'table_prefix\', \''.addslashes($_POST['table_prefix']).'\');
       
   485 define(\'scriptPath\', \''.scriptPath.'\');
       
   486 define(\'contentPath\', \''.$cp.'\');
       
   487 define(\'ENANO_INSTALLED\', \'true\');
       
   488 }
       
   489 $crypto_key = \''.$privkey.'\';
       
   490 ?>';
       
   491 
       
   492   $cf_handle = fopen(ENANO_ROOT.'/config.new.php', 'w');
       
   493   if ( !$cf_handle )
       
   494     return false;
       
   495   fwrite($cf_handle, $config_file);
       
   496   
       
   497   fclose($cf_handle);
       
   498   
       
   499   return true;
       
   500 }
       
   501 
       
   502 function _stg_rename_config_revert()
       
   503 {
       
   504   if ( file_exists('./config.php') )
       
   505   {
       
   506     @rename('./config.php', './config.new.php');
       
   507   }
       
   508   
       
   509   $handle = @fopen('./config.php.new', 'w');
       
   510   if ( !$handle )
       
   511     return false;
       
   512   $contents = '<?php $cryptkey = \'' . _INSTRESUME_AES_KEYBACKUP . '\'; ?>';
       
   513   fwrite($handle, $contents);
       
   514   fclose($handle);
       
   515   return true;
       
   516 }
       
   517 
       
   518 function stg_rename_config()
       
   519 {
       
   520   if ( !@rename('./config.new.php', './config.php') )
       
   521   {
       
   522     echo '<p>Can\'t rename config.php</p>';
       
   523     _stg_rename_config_revert();
       
   524     return false;
       
   525   }
       
   526   
       
   527   if ( $_POST['urlscheme'] == 'tiny' && !file_exists('./.htaccess') )
       
   528   {
       
   529     if ( !@rename('./.htaccess.new', './.htaccess') )
       
   530     {
       
   531       echo '<p>Can\'t rename .htaccess</p>';
       
   532       _stg_rename_config_revert();
       
   533       return false;
       
   534     }
       
   535   }
       
   536   return true;
       
   537 }
       
   538 
       
   539 function stg_start_api_success()
       
   540 {
       
   541   return true;
       
   542 }
       
   543 
       
   544 function stg_start_api_failure()
       
   545 {
       
   546   return false;
       
   547 }
       
   548 
       
   549 function stg_init_logs()
       
   550 {
       
   551   global $db, $session, $paths, $template, $plugins; // Common objects
       
   552   
       
   553   $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs(log_type,action,time_id,date_string,author,page_text,edit_summary) VALUES(\'security\', \'install_enano\', ' . time() . ', \'' . date('d M Y h:i a') . '\', \'' . mysql_real_escape_string($_POST['admin_user']) . '\', \'' . mysql_real_escape_string(ENANO_VERSION) . '\', \'' . mysql_real_escape_string($_SERVER['REMOTE_ADDR']) . '\');');
       
   554   if ( !$q )
       
   555   {
       
   556     echo '<p><tt>MySQL return: ' . mysql_error() . '</tt></p>';
       
   557     return false;
       
   558   }
       
   559   
       
   560   if ( !$session->get_permissions('clear_logs') )
       
   561   {
       
   562     echo '<p><tt>$session: denied clear_logs</tt></p>';
       
   563     return false;
       
   564   }
       
   565   
       
   566   PageUtils::flushlogs('Main_Page', 'Article');
       
   567   
       
   568   return true;
       
   569 }
    67 
   570 
    68 //die('Key size: ' . AES_BITS . '<br />Block size: ' . AES_BLOCKSIZE);
   571 //die('Key size: ' . AES_BITS . '<br />Block size: ' . AES_BLOCKSIZE);
    69 
   572 
    70 if(!function_exists('wikiFormat'))
   573 if(!function_exists('wikiFormat'))
    71 {
   574 {
   991         $cp = scriptPath.'/';
  1494         $cp = scriptPath.'/';
   992         break;
  1495         break;
   993     }
  1496     }
   994     function err($t) { global $template; echo $t; $template->footer(); exit; }
  1497     function err($t) { global $template; echo $t; $template->footer(); exit; }
   995     
  1498     
       
  1499     // $stages = array('connect', 'decrypt', 'genkey', 'parse', 'sql', 'writeconfig', 'renameconfig', 'startapi', 'initlogs');
       
  1500     
   996     if ( !preg_match('/^[a-z0-9_]*$/', $_POST['table_prefix']) )
  1501     if ( !preg_match('/^[a-z0-9_]*$/', $_POST['table_prefix']) )
   997       err('Hacking attempt was detected in table_prefix.');
  1502       err('Hacking attempt was detected in table_prefix.');
   998     
  1503     
   999       echo 'Connecting to MySQL...';
  1504       start_install_table();
  1000       if($_POST['db_root_user'] != '')
  1505       // The stages connect, decrypt, genkey, and parse are preprocessing and don't do any actual data modification.
  1001       {
  1506       // Thus, they need to be run on each retry, e.g. never skipped.
  1002         $conn = mysql_connect($_POST['db_host'], $_POST['db_root_user'], $_POST['db_root_pass']);
  1507       run_installer_stage('connect', 'Connect to MySQL', 'stg_mysql_connect', 'MySQL denied our attempt to connect to the database. This is most likely because your login information was incorrect. You will most likely need to <a href="install.php?mode=license">restart the installation</a>.<br /><br />Error message returned by MySQL: ' . mysql_error(), false);
  1003         if(!$conn) err('Error connecting to MySQL: '.mysql_error());
  1508       if ( isset($_POST['drop_tables']) )
  1004         $q = mysql_query('USE '.$_POST['db_name']);
  1509       {
  1005         if(!$q)
  1510         // Are we supposed to drop any existing tables? If so, do it now
  1006         {
  1511         run_installer_stage('drop', 'Drop existing Enano tables', 'stg_drop_tables', 'This step never returns failure');
  1007           $q = mysql_query('CREATE DATABASE '.$_POST['db_name']);
  1512       }
  1008           if(!$q) err('Error initializing database: '.mysql_error());
  1513       run_installer_stage('decrypt', 'Decrypt administration password', 'stg_decrypt_admin_pass', 'The administration password you entered couldn\'t be decrypted. It is possible that your server did not properly store the encryption key in the configuration file. Please check the file permissions on config.new.php. You may have to return to the login stage of the installation, clear your browser cache, and then rerun this installation.', false);
  1009         }
  1514       run_installer_stage('genkey', 'Generate ' . AES_BITS . '-bit AES private key', 'stg_generate_aes_key', 'Enano encountered an internal error while generating the site encryption key. Please contact the Enano team for support.', false);
  1010         $q = mysql_query('GRANT ALL PRIVILEGES ON '.$_POST['db_name'].'.* TO \''.$_POST['db_user'].'\'@\'localhost\' IDENTIFIED BY \''.$_POST['db_pass'].'\' WITH GRANT OPTION;');
  1515       run_installer_stage('parse', 'Prepare to execute schema file', 'stg_parse_schema', 'Enano encountered an internal error while parsing the SQL file that contains the database structure and initial data. Please contact the Enano team for support.', false);
  1011         if(!$q) err('Could not create the user account');
  1516       run_installer_stage('sql', 'Execute installer schema', 'stg_install', 'The installation failed because an SQL query wasn\'t quite correct. It is possible that you entered malformed data into a form field, or there may be a bug in Enano with your version of MySQL. Please contact the Enano team for support.', false);
  1012         $q = mysql_query('GRANT ALL PRIVILEGES ON '.$_POST['db_name'].'.* TO \''.$_POST['db_user'].'\'@\'%\' IDENTIFIED BY \''.$_POST['db_pass'].'\' WITH GRANT OPTION;');
  1517       run_installer_stage('writeconfig', 'Write configuration files', 'stg_write_config', 'Enano was unable to write the configuration file with your site\'s database credentials. This is almost always because your configuration file does not have the correct permissions. On Windows servers, you may see this message even if the check on the System Requirements page passed. Temporarily running IIS as the Administrator user may help.');
  1013         if(!$q) err('Could not create the user account');
  1518       run_installer_stage('renameconfig', 'Rename configuration files', 'stg_rename_config', 'Enano couldn\'t rename the configuration files to their correct production names. On some UNIX systems, you need to CHMOD the directory with your Enano files to 777 in order for this stage to succeed.');
  1014         mysql_close($conn);
       
  1015       }
       
  1016       $conn = mysql_connect($_POST['db_host'], $_POST['db_user'], $_POST['db_pass']);
       
  1017       if(!$conn) err('Error connecting to MySQL: '.mysql_error());
       
  1018       $q = mysql_query('USE '.$_POST['db_name']);
       
  1019       if(!$q) err('Error selecting database: '.mysql_error());
       
  1020       echo 'done!<br />';
       
  1021       
  1519       
  1022       // Are we supposed to drop any existing tables? If so, do it now
  1520       // Mainstream installation complete - Enano should be usable now
  1023       if(isset($_POST['drop_tables']))
  1521       // The stage of starting the API is special because it has to be called out of function context.
  1024       {
  1522       // To alleviate this, we have two functions, one that returns success and one that returns failure
  1025         echo 'Dropping existing Enano tables...';
  1523       // If the Enano API load is successful, the success function is called to report the action to the user
  1026         // Our list of tables included in Enano
  1524       // If unsuccessful, the failure report is sent
  1027         $tables = Array( 'mdg_categories', 'mdg_comments', 'mdg_config', 'mdg_logs', 'mdg_page_text', 'mdg_session_keys', 'mdg_pages', 'mdg_users', 'mdg_users_extra', 'mdg_themes', 'mdg_buddies', 'mdg_banlist', 'mdg_files', 'mdg_privmsgs', 'mdg_sidebar', 'mdg_hits', 'mdg_search_index', 'mdg_groups', 'mdg_group_members', 'mdg_acl', 'mdg_search_cache', 'mdg_tags', 'mdg_page_groups', 'mdg_page_group_members' );
       
  1028         $tables = implode(', ', $tables);
       
  1029         $tables = str_replace('mdg_', $_POST['table_prefix'], $tables);
       
  1030         $query_of_death = 'DROP TABLE '.$tables.';';
       
  1031         mysql_query($query_of_death); // We won't check for errors here because if this operation fails it probably means the tables didn't exist
       
  1032         echo 'done!<br />';
       
  1033       }
       
  1034       
       
  1035       $cacheonoff = is_writable(ENANO_ROOT.'/cache/') ? '1' : '0';
       
  1036       
       
  1037       echo 'Decrypting administration password...';
       
  1038       
       
  1039       $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE);
       
  1040       
       
  1041       if ( !empty($_POST['crypt_data']) )
       
  1042       {
       
  1043         require('config.new.php');
       
  1044         if ( !isset($cryptkey) )
       
  1045         {
       
  1046           echo 'failed!<br />Cannot get the key from config.new.php';
       
  1047           break;
       
  1048         }
       
  1049         $key = hexdecode($cryptkey);
       
  1050         
       
  1051         $dec = $aes->decrypt($_POST['crypt_data'], $key, ENC_HEX);
       
  1052         
       
  1053       }
       
  1054       else
       
  1055       {
       
  1056         $dec = $_POST['admin_pass'];
       
  1057       }
       
  1058       echo 'done!<br />Generating '.AES_BITS.'-bit AES private key...';
       
  1059       $privkey = $aes->gen_readymade_key();
       
  1060       $pkba = hexdecode($privkey);
       
  1061       $encpass = $aes->encrypt($dec, $pkba, ENC_HEX);
       
  1062       
       
  1063       echo 'done!<br />Preparing for schema execution...';
       
  1064       $schema = file_get_contents('schema.sql');
       
  1065       $schema = str_replace('{{SITE_NAME}}',    mysql_real_escape_string($_POST['sitename']   ), $schema);
       
  1066       $schema = str_replace('{{SITE_DESC}}',    mysql_real_escape_string($_POST['sitedesc']   ), $schema);
       
  1067       $schema = str_replace('{{COPYRIGHT}}',    mysql_real_escape_string($_POST['copyright']  ), $schema);
       
  1068       $schema = str_replace('{{ADMIN_USER}}',   mysql_real_escape_string($_POST['admin_user'] ), $schema);
       
  1069       $schema = str_replace('{{ADMIN_PASS}}',   mysql_real_escape_string($encpass             ), $schema);
       
  1070       $schema = str_replace('{{ADMIN_EMAIL}}',  mysql_real_escape_string($_POST['admin_email']), $schema);
       
  1071       $schema = str_replace('{{ENABLE_CACHE}}', mysql_real_escape_string($cacheonoff          ), $schema);
       
  1072       $schema = str_replace('{{REAL_NAME}}',    '',                                              $schema);
       
  1073       $schema = str_replace('{{TABLE_PREFIX}}', $_POST['table_prefix'],                          $schema);
       
  1074       $schema = str_replace('{{VERSION}}',      ENANO_VERSION,                                   $schema);
       
  1075       $schema = str_replace('{{ADMIN_EMBED_PHP}}', $_POST['admin_embed_php'],                    $schema);
       
  1076       // Not anymore!! :-D
       
  1077       // $schema = str_replace('{{BETA_VERSION}}', ENANO_BETA_VERSION,                              $schema);
       
  1078       
       
  1079       if(isset($_POST['wiki_mode']))
       
  1080       {
       
  1081         $schema = str_replace('{{WIKI_MODE}}', '1', $schema);
       
  1082       }
       
  1083       else
       
  1084       {
       
  1085         $schema = str_replace('{{WIKI_MODE}}', '0', $schema);
       
  1086       }
       
  1087       
       
  1088       // Build an array of queries      
       
  1089       $schema = explode("\n", $schema);
       
  1090       
       
  1091       foreach ( $schema as $i => $sql )
       
  1092       {
       
  1093         $query =& $schema[$i];
       
  1094         $t = trim($query);
       
  1095         if ( empty($t) || preg_match('/^(\#|--)/i', $t) )
       
  1096         {
       
  1097           unset($schema[$i]);
       
  1098           unset($query);
       
  1099         }
       
  1100       }
       
  1101       
       
  1102       $schema = array_values($schema);
       
  1103       $schema = implode("\n", $schema);
       
  1104       $schema = explode(";\n", $schema);
       
  1105       
       
  1106       foreach ( $schema as $i => $sql )
       
  1107       {
       
  1108         $query =& $schema[$i];
       
  1109         if ( substr($query, ( strlen($query) - 1 ), 1 ) != ';' )
       
  1110         {
       
  1111           $query .= ';';
       
  1112         }
       
  1113       }
       
  1114       
       
  1115       // echo '<pre>' . htmlspecialchars(print_r($schema, true)) . '</pre>';
       
  1116       // break;
       
  1117       
       
  1118       echo 'done!<br />Executing schema.sql...';
       
  1119       
       
  1120       // OK, do the loop, baby!!!
       
  1121       foreach($schema as $q)
       
  1122       {
       
  1123         $r = mysql_query($q, $conn);
       
  1124         if(!$r) err('Error during mainstream installation: '.mysql_error());
       
  1125       }
       
  1126       
       
  1127       echo 'done!<br />Writing configuration files...';
       
  1128       if($_POST['urlscheme']=='tiny')
       
  1129       {
       
  1130         $ht = fopen(ENANO_ROOT.'/.htaccess', 'a+');
       
  1131         if(!$ht) err('Error opening file .htaccess for writing');
       
  1132         fwrite($ht, '
       
  1133 RewriteEngine on
       
  1134 RewriteCond %{REQUEST_FILENAME} !-d
       
  1135 RewriteCond %{REQUEST_FILENAME} !-f
       
  1136 RewriteRule ^(.+) '.scriptPath.'/index.php?title=$1 [L,QSA]
       
  1137 RewriteRule \.(php|html|gif|jpg|png|css|js)$ - [L]
       
  1138 ');
       
  1139         fclose($ht);
       
  1140       }
       
  1141   
       
  1142       $config_file = '<?php
       
  1143 /* Enano auto-generated configuration file - editing not recommended! */
       
  1144 $dbhost   = \''.addslashes($_POST['db_host']).'\';
       
  1145 $dbname   = \''.addslashes($_POST['db_name']).'\';
       
  1146 $dbuser   = \''.addslashes($_POST['db_user']).'\';
       
  1147 $dbpasswd = \''.addslashes($_POST['db_pass']).'\';
       
  1148 if ( !defined(\'ENANO_CONSTANTS\') )
       
  1149 {
       
  1150   define(\'ENANO_CONSTANTS\', \'\');
       
  1151   define(\'table_prefix\', \''.addslashes($_POST['table_prefix']).'\');
       
  1152   define(\'scriptPath\', \''.scriptPath.'\');
       
  1153   define(\'contentPath\', \''.$cp.'\');
       
  1154   define(\'ENANO_INSTALLED\', \'true\');
       
  1155 }
       
  1156 $crypto_key = \''.$privkey.'\';
       
  1157 ?>';
       
  1158 
       
  1159       $cf_handle = fopen(ENANO_ROOT.'/config.new.php', 'w');
       
  1160       if(!$cf_handle) err('Couldn\'t open file config.php for writing');
       
  1161       fwrite($cf_handle, $config_file);
       
  1162       fclose($cf_handle);
       
  1163       
       
  1164       echo 'done!<br />Renaming config.new.php and .htaccess.new...';
       
  1165       if ( !@rename('./config.new.php', './config.php') )
       
  1166         err('failed!<p>Please rename config.new.php manually to config.php. If you selected Tiny URLs, please also rename .htaccess.new to .htaccess.');
       
  1167       
       
  1168       if ( $_POST['urlscheme'] == 'tiny' )
       
  1169       {
       
  1170         if ( !@rename('./.htaccess.new', './.htaccess') )
       
  1171           err('failed!<p>Please rename .htaccess.new manually to .htaccess.');
       
  1172       }
       
  1173             
       
  1174       echo 'done!<br />Starting the Enano API...';
       
  1175       
  1525       
  1176       $template_bak = $template;
  1526       $template_bak = $template;
  1177       
  1527       
  1178       // Get Enano loaded
       
  1179       $_GET['title'] = 'Main_Page';
  1528       $_GET['title'] = 'Main_Page';
  1180       require('includes/common.php');
  1529       require('includes/common.php');
  1181       
  1530       
       
  1531       if ( is_object($db) && is_object($session) )
       
  1532       {
       
  1533         run_installer_stage('startapi', 'Start the Enano API', 'stg_start_api_success', '...', false);
       
  1534       }
       
  1535       else
       
  1536       {
       
  1537         run_installer_stage('startapi', 'Start the Enano API', 'stg_start_api_failure', 'The Enano API could not be started. This is an error that should never occur; please contact the Enano team for support.', false);
       
  1538       }
       
  1539       
  1182       // We need to be logged in (with admin rights) before logs can be flushed
  1540       // We need to be logged in (with admin rights) before logs can be flushed
  1183       $session->login_without_crypto($_POST['admin_user'], $dec, false);
  1541       $admin_password = stg_decrypt_admin_pass(true);
       
  1542       $session->login_without_crypto($_POST['admin_user'], $admin_password, false);
  1184       
  1543       
  1185       // Now that login cookies are set, initialize the session manager and ACLs
  1544       // Now that login cookies are set, initialize the session manager and ACLs
  1186       $session->start();
  1545       $session->start();
  1187       $paths->init();
  1546       $paths->init();
  1188       
  1547       
       
  1548       run_installer_stage('initlogs', 'Initialize logs', 'stg_init_logs', '<b>The session manager denied the request to flush logs for the main page.</b><br />
       
  1549                            While under most circumstances you can still <a href="install.php?mode=finish">finish the installation</a>, you should be aware that some servers cannot
       
  1550                            properly set cookies due to limitations with PHP. These limitations are exposed primarily when this issue is encountered during installation. If you choose
       
  1551                            to finish the installation, please be aware that you may be unable to log into your site.');
       
  1552       close_install_table();
       
  1553       
  1189       unset($template);
  1554       unset($template);
  1190       $template =& $template_bak;
  1555       $template =& $template_bak;
  1191       
  1556     
  1192       echo 'done!<br />Initializing logs...';
  1557       echo '<h3>Installation of Enano is complete.</h3><p>Review any warnings above, and then <a href="install.php?mode=finish">click here to finish the installation</a>.';
  1193       
       
  1194       $q = $db->sql_query('INSERT INTO ' . $_POST['table_prefix'] . 'logs(log_type,action,time_id,date_string,author,page_text,edit_summary) VALUES(\'security\', \'install_enano\', ' . time() . ', \'' . date('d M Y h:i a') . '\', \'' . mysql_real_escape_string($_POST['admin_user']) . '\', \'' . mysql_real_escape_string(ENANO_VERSION) . '\', \'' . mysql_real_escape_string($_SERVER['REMOTE_ADDR']) . '\');', $conn);
       
  1195       if ( !$q )
       
  1196         err('Error setting up logs: '.$db->get_error());
       
  1197       
       
  1198       // This is only in RAM; it's meant to correct a race condition encountered by several testers
       
  1199       $session->acl_merge(array(
       
  1200         'clear_logs' => AUTH_ALLOW
       
  1201         ));
       
  1202       
       
  1203       if ( !$session->get_permissions('clear_logs') )
       
  1204       {
       
  1205         echo '<p><b>The session manager denied the request to flush logs for the main page.</b><br />
       
  1206                  While under most circumstances you can still <a href="install.php?mode=finish">finish the installation</a>, you should be aware that some servers cannot
       
  1207                  properly set cookies due to limitations with PHP. These limitations are exposed primarily when this issue is encountered during installation. If you choose
       
  1208                  to finish the installation, please be aware that you may be unable to log into your site.</p>';
       
  1209         break;
       
  1210       }
       
  1211       
       
  1212       // unset($session);
       
  1213       // $session = new sessionManager();
       
  1214       // $session->start();
       
  1215       
       
  1216       PageUtils::flushlogs('Main_Page', 'Article');
       
  1217       
       
  1218       echo 'done!<h3>Installation of Enano is complete.</h3><p>Review any warnings above, and then <a href="install.php?mode=finish">click here to finish the installation</a>.';
       
  1219       
  1558       
  1220       // echo '<script type="text/javascript">window.location="'.scriptPath.'/install.php?mode=finish";</script>';
  1559       // echo '<script type="text/javascript">window.location="'.scriptPath.'/install.php?mode=finish";</script>';
  1221       
  1560       
  1222     break;
  1561     break;
  1223   case "finish":
  1562   case "finish":