public_html/admin/install/lib-install.php
author Dirk Haun <dirk@haun-online.de>
Sat, 17 Oct 2009 13:26:13 +0200
branchHEAD
changeset 7381 e02d71d401c3
parent 7299 dd4e3922f617
child 7427 7915c1f5f403
permissions -rw-r--r--
Creation of multiple plugin groups needs to be fixed in the install script, too
     1 <?php 
     2 
     3 /* Reminder: always indent with 4 spaces (no tabs). */
     4 // +---------------------------------------------------------------------------+
     5 // | Geeklog 1.6                                                               |
     6 // +---------------------------------------------------------------------------+
     7 // | lib-install.php                                                           |
     8 // |                                                                           |
     9 // | Additional functions for install script.                                  |
    10 // +---------------------------------------------------------------------------+
    11 // | Copyright (C) 2008-2009 by the following authors:                         |
    12 // |                                                                           |
    13 // | Authors: Matt West - matt.danger.west AT gmail DOT com                    |
    14 // |          Dirk Haun - dirk AT haun-online DOT de                           |
    15 // +---------------------------------------------------------------------------+
    16 // |                                                                           |
    17 // | This program is free software; you can redistribute it and/or             |
    18 // | modify it under the terms of the GNU General Public License               |
    19 // | as published by the Free Software Foundation; either version 2            |
    20 // | of the License, or (at your option) any later version.                    |
    21 // |                                                                           |
    22 // | This program is distributed in the hope that it will be useful,           |
    23 // | but WITHOUT ANY WARRANTY; without even the implied warranty of            |
    24 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             |
    25 // | GNU General Public License for more details.                              |
    26 // |                                                                           |
    27 // | You should have received a copy of the GNU General Public License         |
    28 // | along with this program; if not, write to the Free Software Foundation,   |
    29 // | Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           |
    30 // |                                                                           |
    31 // +---------------------------------------------------------------------------+
    32 
    33 /**
    34  * The functionality of many of these functions already exists in other
    35  * Geeklog libraries. However, during the first few stages of the
    36  * installation either those libraries cannot be accessed or dependency 
    37  * libraries cannot be accessed.
    38  */
    39 
    40 if (strpos(strtolower($_SERVER['PHP_SELF']), 'lib-install.php') !== false) {
    41     die('This file can not be used on its own!');
    42 }
    43 
    44 // this should help expose parse errors even when
    45 // display_errors is set to Off in php.ini
    46 if (function_exists('ini_set')) {
    47     ini_set('display_errors', '1');
    48 }
    49 error_reporting(E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR | E_NOTICE);
    50 
    51 if (!defined('LB')) {
    52     define('LB', "\n");
    53 }
    54 if (!defined('VERSION')) {
    55     /**
    56     * This constant defines Geeklog's version number. It will be written to
    57     * siteconfig.php and the database (in the latter case minus any suffix).
    58     */
    59     define('VERSION', '1.6.1hg');
    60 }
    61 if (!defined('XHTML')) {
    62     define('XHTML', ' /');
    63 }
    64 if (!defined('SUPPORTED_PHP_VER')) {
    65     define('SUPPORTED_PHP_VER', '4.3.0');
    66 }
    67 if (!defined('SUPPORTED_MYSQL_VER')) {
    68     define('SUPPORTED_MYSQL_VER', '3.23.2');
    69 }
    70 
    71 $_REQUEST = array_merge($_GET, $_POST);
    72 
    73 if (empty($LANG_DIRECTION)) {
    74     $LANG_DIRECTION = 'ltr';
    75 }
    76 if ($LANG_DIRECTION == 'rtl') {
    77     $form_label_dir = 'form-label-right';
    78     $perms_label_dir = 'perms-label-right';
    79 } else {
    80     $form_label_dir = 'form-label-left';
    81     $perms_label_dir = 'perms-label-left';
    82 }
    83 
    84 $language = INST_getLanguage();
    85 // Include the language file
    86 require_once 'language/' . $language . '.php'; 
    87 
    88 // Before we begin, check if an uploaded file exceeds PHP's post_max_size
    89 if (isset($_SERVER['CONTENT_LENGTH'])) {
    90 
    91     // This code is thanks to v3 AT sonic-world DOT ru via PHP.net
    92     $POST_MAX_SIZE = ini_get('post_max_size');
    93     $mul = substr($POST_MAX_SIZE, -1);
    94     $mul = ($mul == 'M' 
    95             ? 1048576 
    96             : ( $mul == 'K' 
    97                 ? 1024 
    98                 : ( $mul == 'G' 
    99                     ? 1073741824 
   100                     : 1 ) ) );
   101 
   102     if (($_SERVER['CONTENT_LENGTH'] > ($mul*((int)$POST_MAX_SIZE))) && $POST_MAX_SIZE) {
   103 
   104         // If it does, display an error message
   105         $display = INST_getHeader($LANG_ERROR[8])
   106             . INST_getAlertMsg($LANG_ERROR[7])
   107             . INST_getFooter();
   108         die($display);
   109 
   110     }
   111 
   112 }
   113 
   114 
   115 
   116 // +---------------------------------------------------------------------------+
   117 // | Functions                                                                 |
   118 // +---------------------------------------------------------------------------+
   119 
   120 /**
   121  * Returns the beginning HTML for the installer theme.
   122  *
   123  * @param   $mHeading   Heading
   124  * @return  string      Header HTML code
   125  *
   126  */
   127 function INST_getHeader($mHeading)
   128 {
   129     global $LANG_CHARSET, $LANG_INSTALL, $LANG_DIRECTION;
   130 
   131     return (defined('XHTML') 
   132             ? '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' 
   133                 . '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'
   134             : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">' 
   135                 . '<html>' ) 
   136         . '<head>
   137 <meta http-equiv="Content-Type" content="text/html;charset=' . $LANG_CHARSET . '"' . XHTML . '>
   138 <meta name="robots" content="noindex,nofollow"' . XHTML . '>
   139 <meta http-equiv="Cache-Control" content="no-cache/"/>
   140 <meta http-equiv="Pragma" content="no-cache"/>
   141 <meta http-equiv="Expires" content="-1"/>
   142 <link rel="stylesheet" type="text/css" href="layout/style.css"' . XHTML . '>
   143 <script language="javascript" type="text/javascript">
   144 function INST_selectMigrationType() 
   145 {
   146     var myType = document.migrate.migration_type.value;  
   147     var migrationSelect = document.getElementById("migration-select");
   148     var migrationUpload = document.getElementById("migration-upload");
   149     var migrationUploadWarning = document.getElementById("migration-upload-warning");
   150 
   151     switch (myType) {
   152         case "select":
   153           migrationSelect.style.display = "inline";
   154           migrationUpload.style.display = "none";
   155           migrationUploadWarning.style.display = "none";
   156           break;l
   157         case "upload":
   158           migrationSelect.style.display = "none";
   159           migrationUpload.style.display = "inline";
   160           migrationUploadWarning.style.display = "block";
   161           break;
   162         default:
   163           migrationSelect.style.display = "none";
   164           migrationUpload.style.display = "none";
   165           migrationUploadWarning.style.display = "none";
   166     }
   167 }
   168 </script>
   169 <title>' . $LANG_INSTALL[0] . '</title>
   170 </head>
   171 
   172 <body dir="' . $LANG_DIRECTION . '">
   173     <div class="header-navigation-container">
   174         <div class="header-navigation-line">
   175             <a href="' . $LANG_INSTALL[87] . '" class="header-navigation">' . $LANG_INSTALL[1] . '</a>&nbsp;&nbsp;&nbsp;
   176         </div>
   177     </div>
   178     <div class="header-logobg-container-inner">
   179         <a class="header-logo" href="http://www.geeklog.net/">
   180             <img src="layout/logo.png"  width="151" height="56" alt="Geeklog"' . XHTML . '>
   181         </a>
   182         <div class="header-slogan">' . $LANG_INSTALL[2] . ' <br' . XHTML . '><br' . XHTML . '>
   183         </div>
   184     </div>
   185     <div class="installation-container">
   186         <div class="installation-body-container">
   187             <h1 class="heading">' . $mHeading . '</h1>' . LB;
   188 
   189 }
   190 
   191 /**
   192  * Returns the ending HTML for the installer theme.
   193  *
   194  * @return string Footer HTML code
   195  *
   196  */
   197 function INST_getFooter()
   198 {
   199     return '<br' . XHTML . '><br' . XHTML . '>' . LB
   200         . '</div>' . LB
   201         . '</div>' . LB
   202         . '</body>' . LB 
   203         . '</html>';
   204 }
   205 
   206 /**
   207  * Returns the PHP version
   208  *
   209  * Note: Removes appendices like 'rc1', etc.
   210  *
   211  * @return array the 3 separate parts of the PHP version number
   212  *
   213  */
   214 function php_v()
   215 {
   216     $phpv = explode('.', phpversion());
   217 
   218     return array($phpv[0], $phpv[1], (int) $phpv[2]);
   219 }
   220 
   221 /**
   222  * Check if the user's PHP version is supported by Geeklog
   223  *
   224  * @return bool True if supported, falsed if not supported
   225  *
   226  */
   227 function INST_phpOutOfDate()
   228 {
   229     $minv = explode('.', SUPPORTED_PHP_VER);
   230 
   231     $phpv = php_v();
   232     if (($phpv[0] <  $minv[0]) ||
   233        (($phpv[0] == $minv[0]) && ($phpv[1] <  $minv[1])) ||
   234        (($phpv[0] == $minv[0]) && ($phpv[1] == $minv[1]) && ($phpv[2] < $minv[2]))) {
   235         return true;    
   236     }
   237 
   238     return false;
   239 }
   240 
   241 /**
   242  * Returns the MySQL version
   243  *
   244  * @return  mixed   array[0..2] of the parts of the version number or false
   245  *
   246  */
   247 function mysql_v($_DB_host, $_DB_user, $_DB_pass)
   248 {
   249     $db_handle = @mysql_connect($_DB_host, $_DB_user, $_DB_pass);
   250     if ($db_handle === false) {
   251         return false;
   252     }
   253 
   254     $mysqlv = @mysql_get_server_info($db_handle);
   255 
   256     if (!empty($mysqlv)) {
   257         preg_match('/^([0-9]+).([0-9]+).([0-9]+)/', $mysqlv, $match);
   258         $mysqlmajorv = $match[1];
   259         $mysqlminorv = $match[2];
   260         $mysqlrev = $match[3];
   261     } else {
   262         $mysqlmajorv = 0;
   263         $mysqlminorv = 0;
   264         $mysqlrev = 0;
   265     }
   266     @mysql_close($db_handle);
   267 
   268     return array($mysqlmajorv, $mysqlminorv, $mysqlrev);
   269 }
   270 
   271 /**
   272  * Check if the user's MySQL version is supported by Geeklog
   273  *
   274  * @param   array   $db     Database information
   275  * @return  bool    True if supported, falsed if not supported
   276  *
   277  */
   278 function INST_mysqlOutOfDate($db)
   279 {
   280     $minv = explode('.', SUPPORTED_MYSQL_VER);
   281 
   282     if ($db['type'] == 'mysql' || $db['type'] == 'mysql-innodb') {
   283         $myv = mysql_v($db['host'], $db['user'], $db['pass']);
   284 
   285         if (($myv[0] <  $minv[0]) ||
   286            (($myv[0] == $minv[0]) && ($myv[1] <  $minv[1])) ||
   287            (($myv[0] == $minv[0]) && ($myv[1] == $minv[1]) && ($myv[2] < $minv[2]))) {
   288 
   289             return true;
   290         }
   291     }
   292 
   293     return false;
   294 }
   295 
   296 /**
   297  * Written to aid in install script development 
   298  *
   299  * NOTE:    This code is a modified copy from PHP.net
   300  *
   301  * @param   int $size       Filesize
   302  * @param   int $dec_places Number of decimal places
   303  * @return  string          Filesize string
   304  *
   305  */
   306 function INST_formatSize($size, $dec_places = 0) 
   307 {
   308     $sizes = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
   309     for ($i=0; ($size > 1024 && isset($sizes[$i+1])) ; $i++) {
   310         $size /= 1024;
   311     }
   312     return  round($size, $dec_places) . " " . $sizes[$i];
   313 }
   314 
   315 /**
   316  * Provide a link to the help page for an option
   317  *
   318  * @param   string  $var    key of the label, used as an anchor on the help page
   319  * @return  string          HTML for the link
   320  *
   321  */
   322 function INST_helpLink($var)
   323 {
   324     global $language;
   325 
   326     return '(<a href="help.php?language=' . $language . '&amp;label=' . $var
   327            . '#' . $var . '" target="_blank">?</a>)';
   328 }
   329 
   330 /**
   331  * Make a nice display name from the language filename
   332  *
   333  * NOTE:     This code is a straight copy from MBYTE_languageList()
   334  *
   335  * @param    string  $file   filename without the extension
   336  * @return   string          language name to display to the user
   337  *
   338  */
   339 function INST_prettifyLanguageName($filename)
   340 {
   341     $langfile = str_replace('_utf-8', '', $filename);
   342     $uscore = strpos($langfile, '_');
   343     if ($uscore === false) {
   344         $lngname = ucfirst($langfile);
   345     } else {
   346         $lngname = ucfirst(substr($langfile, 0, $uscore));
   347         $lngadd = substr($langfile, $uscore + 1);
   348         $lngadd = str_replace('utf-8', '', $lngadd);
   349         $lngadd = str_replace('_', ', ', $lngadd);
   350         $word = explode(' ', $lngadd);
   351         $lngadd = '';
   352         foreach ($word as $w) {
   353             if (preg_match('/[0-9]+/', $w)) {
   354                 $lngadd .= strtoupper($w) . ' ';
   355             } else {
   356                 $lngadd .= ucfirst($w) . ' ';
   357             }
   358         }
   359         $lngname .= ' (' . trim($lngadd) . ')';
   360     }
   361 
   362     return $lngname;
   363 }
   364 
   365 /**
   366  * Modify db-config.php
   367  *
   368  * @param   string  $config_file    Full path to db-config.php
   369  * @param   array   $db             Database information to save
   370  * @return  bool    True if successful, false if not
   371  *
   372  */
   373 function INST_writeConfig($config_file, $db)
   374 {
   375     // we may have included db-config.php elsewhere already, in which case
   376     // all of these variables need to be imported from the global namespace
   377     global $_DB_host, $_DB_name, $_DB_user, $_DB_pass, $_DB_table_prefix,
   378            $_DB_dbms;
   379 
   380     require_once $config_file; // Grab the current DB values
   381 
   382     $db = array('host' => (isset($db['host']) ? $db['host'] : $_DB_host),
   383                 'name' => (isset($db['name']) ? $db['name'] : $_DB_name),
   384                 'user' => (isset($db['user']) ? $db['user'] : $_DB_user),
   385                 'pass' => (isset($db['pass']) ? $db['pass'] : $_DB_pass),
   386                 'table_prefix' => (isset($db['table_prefix']) ? $db['table_prefix'] : $_DB_table_prefix),
   387                 'type' => (isset($db['type']) ? $db['type'] : $_DB_dbms) );
   388     if ($db['type'] == 'mysql-innodb') {
   389         $db['type'] = 'mysql';
   390     }
   391 
   392     // Read in db-config.php so we can insert the DB information
   393     $dbconfig_file = fopen($config_file, 'rb');
   394     $dbconfig_data = fread($dbconfig_file, filesize($config_file));
   395     fclose($dbconfig_file);
   396 
   397     // Replace the values with the new ones
   398     $dbconfig_data = str_replace("\$_DB_host = '" . $_DB_host . "';", "\$_DB_host = '" . $db['host'] . "';", $dbconfig_data); // Host
   399     $dbconfig_data = str_replace("\$_DB_name = '" . $_DB_name . "';", "\$_DB_name = '" . $db['name'] . "';", $dbconfig_data); // Database
   400     $dbconfig_data = str_replace("\$_DB_user = '" . $_DB_user . "';", "\$_DB_user = '" . $db['user'] . "';", $dbconfig_data); // Username
   401     $dbconfig_data = str_replace("\$_DB_pass = '" . $_DB_pass . "';", "\$_DB_pass = '" . $db['pass'] . "';", $dbconfig_data); // Password
   402     $dbconfig_data = str_replace("\$_DB_table_prefix = '" . $_DB_table_prefix . "';", "\$_DB_table_prefix = '" . $db['table_prefix'] . "';", $dbconfig_data); // Table prefix
   403     $dbconfig_data = str_replace("\$_DB_dbms = '" . $_DB_dbms . "';", "\$_DB_dbms = '" . $db['type'] . "';", $dbconfig_data); // Database type ('mysql' or 'mssql')
   404 
   405     // Write our changes to db-config.php
   406     $dbconfig_file = fopen($config_file, 'wb');
   407     if (!fwrite($dbconfig_file, $dbconfig_data)) {
   408         return false;
   409     }
   410     fclose($dbconfig_file);
   411     return true;
   412 }
   413 
   414 /**
   415  * Check if a table exists
   416  * @see DB_checkTableExists
   417  *
   418  *
   419  * @param   string $table   Table name
   420  * @return  boolean         True if table exists, false if it does not
   421  *
   422  */
   423 function INST_checkTableExists($table)
   424 {
   425     return DB_checkTableExists($table);
   426 }
   427 
   428 /**
   429  * Can the install script connect to the database?
   430  *
   431  * @param   array   $db Database information
   432  * @return  mixed       Returns the DB handle if true, false if not
   433  *
   434  */
   435 function INST_dbConnect($db)
   436 {
   437     if (empty($db['pass'])) {
   438         return false;
   439     }
   440     $db_handle = false;
   441     switch ($db['type']) {
   442     case 'mysql-innodb':
   443         // deliberate fallthrough - no "break"
   444     case 'mysql':
   445         if ($db_handle = @mysql_connect($db['host'], $db['user'], $db['pass'])) {
   446             return $db_handle;
   447         }
   448         break;
   449     case 'mssql':
   450         if ($db_handle = @mssql_connect($db['host'], $db['user'], $db['pass'])) {
   451             return $db_handle;
   452         }
   453         break;
   454     }
   455     return $db_handle;
   456 }
   457 
   458 /**
   459  * Check if a Geeklog database exists
   460  *
   461  * @param   array   $db Array containing connection info
   462  * @return  bool        True if a database exists, false if not
   463  *
   464  */
   465 function INST_dbExists($db)
   466 {
   467     $db_handle = INST_dbConnect($db);
   468     $db_exists = false;
   469     switch ($db['type']) {
   470     case 'mysql':
   471         // deliberate fallthrough - no "break"
   472     case 'mysql-innodb':
   473         if (@mysql_select_db($db['name'], $db_handle)) {
   474             return true;
   475         }
   476         break;
   477     case 'mssql':
   478         if (@mssql_select_db($db['name'], $db_handle)) {
   479             return true;
   480         }
   481         break;
   482     }
   483     return false;
   484 }
   485 
   486 /**
   487  * Check if URL exists
   488  *
   489  * NOTE:    This code is a modified copy from marufit at gmail dot com
   490  *
   491  * @param   string  $url    URL
   492  * @return  bool            True if URL exists, false if not
   493  *
   494  */
   495 function INST_urlExists($url) 
   496 {
   497 /*
   498     $handle = curl_init($url);
   499     if ($handle === false) {
   500         return false;
   501     }
   502     curl_setopt($handle, CURLOPT_HEADER, false);
   503     curl_setopt($handle, CURLOPT_FAILONERROR, true);  // this works
   504     curl_setopt($handle, CURLOPT_NOBODY, true);
   505     curl_setopt($handle, CURLOPT_RETURNTRANSFER, false);
   506     $response = curl_exec($handle);
   507     curl_close($handle);
   508     return $response;
   509 */
   510     return true;
   511 }
   512 
   513 /**
   514  * Check if an error occured while uploading a file
   515  *
   516  * @param   array   $mFile  $_FILE['uploaded_file']
   517  * @return  mixed           Returns the error string if an error occured,
   518  *                          returns false if no error occured
   519  *
   520  */
   521 function INST_getUploadError($mFile) 
   522 {
   523     global $LANG_ERROR;
   524 
   525     $mRetval = '';
   526     $mErrors = array(
   527         UPLOAD_ERR_INI_SIZE => $LANG_ERROR[0],
   528         UPLOAD_ERR_FORM_SIZE => $LANG_ERROR[1],
   529         UPLOAD_ERR_PARTIAL => $LANG_ERROR[2],
   530         UPLOAD_ERR_NO_FILE => $LANG_ERROR[3],
   531         UPLOAD_ERR_NO_TMP_DIR => $LANG_ERROR[4],
   532         UPLOAD_ERR_CANT_WRITE => $LANG_ERROR[5],
   533         UPLOAD_ERR_EXTENSION => $LANG_ERROR[6]);
   534 
   535     if ($mFile['error'] !== UPLOAD_ERR_OK) { // If an error occured while uploading the file.
   536 
   537         if ($mFile['error'] > count($mErrors)) { // If the error code isn't listed in $mErrors
   538 
   539             $mRetval = 'An unknown error occured'; // Unknown error
   540 
   541         } else {
   542 
   543             $mRetval = $mErrors[$mFile['error']]; // Print the error
   544 
   545         }
   546 
   547     } else { // If no upload error occurred
   548 
   549         $mRetval = false;
   550 
   551     }
   552     
   553     return $mRetval;
   554 }
   555 
   556 /**
   557  * Check which plugins are actually installed and disable them if needed
   558  *
   559  * @return   int     number of plugins that were disabled
   560  *
   561  */
   562 function INST_checkPlugins()
   563 {
   564     global $_CONF, $_TABLES;
   565 
   566     $disabled = 0;
   567     $plugin_path = $_CONF['path'] . 'plugins/';
   568 
   569     $result = DB_query("SELECT pi_name FROM {$_TABLES['plugins']} WHERE pi_enabled = 1");
   570     $num_plugins = DB_numRows($result);
   571     for ($i = 0; $i < $num_plugins; $i++) {
   572         $A = DB_fetchArray($result);
   573         if (!file_exists($plugin_path . $A['pi_name'] . '/functions.inc')) {
   574             DB_query("UPDATE {$_TABLES['plugins']} SET pi_enabled = 0 WHERE pi_name = '{$A['pi_name']}'");
   575             $disabled++;
   576         }
   577     }
   578 
   579     return $disabled;
   580 }
   581 
   582 /**
   583  * Nicely formats the alert messages
   584  *
   585  * @param    $mMessage   Message string
   586  * @param    $mType      'error', 'warning', 'success', or 'notice'
   587  * @return   string      HTML formatted dialog message
   588  *
   589  */
   590 function INST_getAlertMsg($mMessage, $mType = 'notice')
   591 {
   592     global $LANG_INSTALL;
   593 
   594     $mStyle = ($mType == 'success') ? 'success' : 'error';
   595 
   596     switch (strtolower($mType)) {
   597     case 'error':
   598         $mType = $LANG_INSTALL[38]; break;
   599     case 'warning':
   600         $mType = $LANG_INSTALL[20]; break;
   601     case 'success':
   602         $mType = $LANG_INSTALL[93]; break;
   603     default:
   604         $mType = $LANG_INSTALL[59]; break;
   605     }
   606 
   607     return '<div class="notice"><span class="' . $mStyle . '">' . $mType .':</span> ' 
   608         . $mMessage . '</div>' . LB;
   609 
   610 }
   611 
   612 /**
   613  * Check if we can skip upgrade steps (post-1.5.0)
   614  *
   615  * If we're doing an upgrade from 1.5.0 or later and we have the necessary
   616  * DB credentials, skip the forms and upgrade directly.
   617  *
   618  * NOTE:    Will not return if upgrading from 1.5.0 or later.
   619  *
   620  * @param   string  $dbconfig_path      path to db-config.php
   621  * @param   string  $siteconfig_path    path to siteconfig.php
   622  * @return  string                      database version, if possible
   623  *
   624  */
   625 function INST_checkPost150Upgrade($dbconfig_path, $siteconfig_path)
   626 {
   627     global $_CONF, $_TABLES, $_DB, $_DB_dbms, $_DB_host, $_DB_user, $_DB_pass,
   628            $language;
   629 
   630     require $dbconfig_path;
   631     require $siteconfig_path;
   632 
   633     $connected = false;
   634     $version = '';
   635 
   636     switch ($_DB_dbms) {
   637     case 'mysql':
   638         $db_handle = @mysql_connect($_DB_host, $_DB_user, $_DB_pass);
   639         if ($db_handle) {
   640             $connected = @mysql_select_db($_DB_name, $db_handle);
   641         }
   642         break;
   643 
   644     case 'mssql':    
   645         $db_handle = @mssql_connect($_DB_host, $_DB_user, $_DB_pass);
   646         if ($db_handle) {
   647             $connected = @mssql_select_db($_DB_name, $db_handle);
   648         }
   649         break;
   650 
   651     default:
   652         $connected = false;
   653         break;
   654     }
   655 
   656     if ($connected) {
   657         require $_CONF['path_system'] . 'lib-database.php';
   658 
   659         $version = INST_identifyGeeklogVersion();
   660 
   661         switch ($_DB_dbms) {
   662         case 'mysql':
   663             @mysql_close($db_handle);
   664             break;
   665 
   666         case 'mssql':
   667             @mssql_close($db_handle);
   668             break;
   669         }
   670 
   671         if (!empty($version) && ($version != VERSION) &&
   672                 (version_compare($version, '1.5.0') >= 0)) {
   673 
   674             // current version is at least 1.5.0, so upgrade directly
   675             $req_string = 'index.php?mode=upgrade&step=3'
   676                         . '&dbconfig_path=' . $dbconfig_path
   677                         . '&language=' . $language
   678                         . '&version=' . $version;
   679 
   680             header('Location: ' . $req_string);
   681             exit;
   682         }
   683     }
   684 
   685     return $version;
   686 }
   687 
   688 
   689 /**
   690 * Get information about a plugin
   691 *
   692 * Only works for plugins that have a autoinstall.php file
   693 *
   694 * @param    string  $plugin     plugin's directory name
   695 * @return   mixed               array of plugin info or false: error
   696 *
   697 */
   698 function INST_getPluginInfo($plugin)
   699 {
   700     global $_CONF, $_TABLES, $_DB_dbms, $_DB_table_prefix;
   701 
   702     $info = false;
   703 
   704     $autoinstall = $_CONF['path'] . 'plugins/' . $plugin . '/autoinstall.php';
   705     if (! file_exists($autoinstall)) {
   706         return false;
   707     }
   708 
   709     include $autoinstall;
   710 
   711     $fn = 'plugin_autoinstall_' . $plugin;
   712     if (function_exists($fn)) {
   713         $inst_info = $fn($plugin);
   714         if (isset($inst_info['info']) &&
   715                 !empty($inst_info['info']['pi_name'])) {
   716             $info = $inst_info['info'];
   717         }
   718     }
   719 
   720     return $info;
   721 }
   722 
   723 /**
   724 * Do the actual plugin auto install
   725 *
   726 * @param    string  $plugin     Plugin name
   727 * @param    array   $inst_parm  Installation parameters for the plugin
   728 * @param    boolean $verbose    true: enable verbose logging
   729 * @return   boolean             true on success, false otherwise
   730 *
   731 */
   732 function INST_pluginAutoinstall($plugin, $inst_parms, $verbose = true)
   733 {
   734     global $_CONF, $_TABLES, $_USER, $_DB_dbms, $_DB_table_prefix;
   735 
   736     $fake_uid = false;
   737     if (!isset($_USER['uid'])) {
   738         $_USER['uid'] = 1;
   739         $fake_uid = false;
   740     }
   741 
   742     $base_path = $_CONF['path'] . 'plugins/' . $plugin . '/';
   743 
   744     if ($verbose) {
   745         COM_errorLog("Attempting to install the '$plugin' plugin", 1);
   746     }
   747 
   748     // sanity checks for $inst_parms
   749     if (isset($inst_parms['info'])) {
   750         $pi_name       = $inst_parms['info']['pi_name'];
   751         $pi_version    = $inst_parms['info']['pi_version'];
   752         $pi_gl_version = $inst_parms['info']['pi_gl_version'];
   753         $pi_homepage   = $inst_parms['info']['pi_homepage'];
   754     }
   755     if (empty($pi_name) || ($pi_name != $plugin) || empty($pi_version) ||
   756             empty($pi_gl_version) || empty($pi_homepage)) {
   757         COM_errorLog('Incomplete plugin info', 1);
   758 
   759         return false;
   760     }
   761 
   762     // add plugin tables, if any
   763     if (! empty($inst_parms['tables'])) {
   764         $tables = $inst_parms['tables'];                                       
   765         foreach ($tables as $table) {
   766             $_TABLES[$table] = $_DB_table_prefix . $table;
   767         }
   768     }
   769 
   770     // Create the plugin's group(s), if any
   771     $groups = array();
   772     $admin_group_id = 0;
   773     if (! empty($inst_parms['groups'])) {
   774         $groups = $inst_parms['groups'];
   775         foreach ($groups as $name => $desc) {
   776             if ($verbose) {
   777                 COM_errorLog("Attempting to create '$name' group", 1);
   778             }
   779 
   780             $grp_name = addslashes($name);
   781             $grp_desc = addslashes($desc);
   782             DB_query("INSERT INTO {$_TABLES['groups']} (grp_name, grp_descr) VALUES ('$grp_name', '$grp_desc')", 1);
   783             if (DB_error()) {
   784                 COM_errorLog('Error creating plugin group', 1);
   785                 PLG_uninstall($plugin);
   786 
   787                 return false;
   788             }
   789 
   790             // keep the new group's ID for use in the mappings section (below)
   791             $groups[$name] = DB_insertId();
   792 
   793             // assume that the first group is the plugin's Admin group
   794             if ($admin_group_id == 0) {
   795                 $admin_group_id = $groups[$name];
   796             }
   797         }
   798     }
   799 
   800     // Create the plugin's table(s)
   801     $_SQL = array();
   802     $DEFVALUES = array();
   803     if (file_exists($base_path . 'sql/' . $_DB_dbms . '_install.php')) {
   804         require_once $base_path . 'sql/' . $_DB_dbms . '_install.php';
   805     }
   806 
   807     if (count($_SQL) > 0) {
   808         $use_innodb = false;
   809         if (($_DB_dbms == 'mysql') &&
   810             (DB_getItem($_TABLES['vars'], 'value', "name = 'database_engine'")
   811                 == 'InnoDB')) {
   812             $use_innodb = true;
   813         }
   814 
   815         foreach ($_SQL as $sql) {
   816             $sql = str_replace('#group#', $admin_group_id, $sql);
   817             if ($use_innodb) {
   818                 $sql = str_replace('MyISAM', 'InnoDB', $sql);
   819             }
   820             DB_query($sql);
   821             if (DB_error()) {
   822                 COM_errorLog('Error creating plugin table', 1);
   823                 PLG_uninstall($plugin);
   824 
   825                 return false;
   826             }
   827         }
   828     }
   829 
   830     // Add the plugin's features
   831     if ($verbose) {
   832         COM_errorLog("Attempting to add '$plugin' features", 1);
   833     }
   834 
   835     $features = array();
   836     $mappings = array();
   837     if (!empty($inst_parms['features'])) {
   838         $features = $inst_parms['features'];
   839         if (!empty($inst_parms['mappings'])) {
   840             $mappings = $inst_parms['mappings'];
   841         }
   842 
   843         foreach ($features as $feature => $desc) {
   844             $ft_name = addslashes($feature);
   845             $ft_desc = addslashes($desc);
   846             DB_query("INSERT INTO {$_TABLES['features']} (ft_name, ft_descr) "
   847                      . "VALUES ('$ft_name', '$ft_desc')", 1);
   848             if (DB_error()) {
   849                 COM_errorLog('Error adding plugin feature', 1);
   850                 PLG_uninstall($plugin);
   851 
   852                 return false;
   853             }
   854 
   855             $feat_id = DB_insertId();
   856 
   857             if (isset($mappings[$feature])) {
   858                 foreach ($mappings[$feature] as $group) {
   859                     if ($verbose) {
   860                         COM_errorLog("Adding '$feature' feature to the '$group' group", 1);
   861                     }
   862 
   863                     DB_query("INSERT INTO {$_TABLES['access']} (acc_ft_id, acc_grp_id) VALUES ($feat_id, {$groups[$group]})");
   864                     if (DB_error()) {
   865                         COM_errorLog('Error mapping plugin feature', 1);
   866                         PLG_uninstall($plugin);
   867 
   868                         return false;
   869                     }
   870                 }
   871             }
   872         }
   873     }
   874 
   875     // Add plugin's Admin group to the Root user group 
   876     // (assumes that the Root group's ID is always 1)
   877     if (count($groups) > 0) {
   878         if ($verbose) {
   879             COM_errorLog("Attempting to give all users in the Root group access to the '$plugin' Admin group", 1);
   880         }
   881 
   882         foreach ($groups as $key => $value) {
   883             DB_query("INSERT INTO {$_TABLES['group_assignments']} VALUES "
   884                      . "($admin_group_id, NULL, 1)");
   885             if (DB_error()) {
   886                 COM_errorLog('Error adding plugin admin group to Root group', 1);
   887                 PLG_uninstall($plugin);
   888 
   889                 return false;
   890             }
   891         }
   892     }
   893 
   894     // Pre-populate tables or run any other SQL queries
   895     if (count($DEFVALUES) > 0) {
   896         if ($verbose) {
   897             COM_errorLog('Inserting default data', 1);
   898         }
   899         foreach ($DEFVALUES as $sql) {
   900             $sql = str_replace('#group#', $admin_group_id, $sql);
   901             DB_query($sql, 1);
   902             if (DB_error()) {
   903                 COM_errorLog('Error adding plugin default data', 1);
   904                 PLG_uninstall($plugin);
   905             
   906                 return false;
   907             }
   908         }
   909     }
   910 
   911     // Load the online configuration records
   912     $load_config = 'plugin_load_configuration_' . $plugin;
   913     if (function_exists($load_config)) {
   914         if (! $load_config($plugin)) {
   915             COM_errorLog('Error loading plugin configuration', 1);
   916             PLG_uninstall($plugin);
   917 
   918             return false;
   919         }
   920 
   921         require_once $_CONF['path'] . 'system/classes/config.class.php';
   922         $config =& config::get_instance();
   923         $config->initConfig(); // force re-reading, including new plugin conf
   924     }
   925 
   926     // Finally, register the plugin with Geeklog
   927     if ($verbose) {
   928         COM_errorLog("Registering '$plugin' plugin", 1);
   929     }
   930 
   931     // silently delete an existing entry
   932     DB_delete($_TABLES['plugins'], 'pi_name', $plugin);
   933 
   934     DB_query("INSERT INTO {$_TABLES['plugins']} (pi_name, pi_version, pi_gl_version, pi_homepage, pi_enabled) VALUES "
   935         . "('$plugin', '$pi_version', '$pi_gl_version', '$pi_homepage', 1)");
   936 
   937     if (DB_error()) {
   938         COM_errorLog('Failed to register plugin', 1);
   939         PLG_uninstall($plugin);
   940 
   941         return false;
   942     }
   943 
   944     // give the plugin a chance to perform any post-install operations
   945     $post_install = 'plugin_postinstall_' . $plugin;
   946     if (function_exists($post_install)) {
   947         if (! $post_install($plugin)) {
   948             COM_errorLog('Plugin postinstall failed', 1);
   949             PLG_uninstall($plugin);
   950 
   951             return false;
   952         }   
   953     }
   954 
   955     if ($verbose) {
   956         COM_errorLog("Successfully installed the '$plugin' plugin!", 1);
   957     }
   958 
   959     if ($fake_uid) {
   960         unset($_USER['uid']);
   961     }
   962 
   963     return true;
   964 }
   965 
   966 
   967 /**
   968 * Do a sanity check on the paths and URLs
   969 *
   970 * This is somewhat speculative but should provide the user with a working
   971 * site even if, for example, a site backup was installed elsewhere.
   972 *
   973 * @param    string  $path           proper /path/to/Geeklog
   974 * @param    string  $path_html      path to public_html
   975 * @param    string  $site_url       The site's URL
   976 * @param    string  $site_admin_url URL to the admin directory
   977 *
   978 */
   979 function INST_fixPathsAndUrls($path, $path_html, $site_url, $site_admin_url)
   980 {
   981     // no "global $_CONF" here!
   982 
   983     require_once $path . 'system/classes/config.class.php';
   984 
   985     $config = config::get_instance();
   986     $config->set_configfile($path . 'db-config.php');
   987     $config->load_baseconfig();
   988     $config->initConfig();
   989     $_CONF = $config->get_config('Core');
   990 
   991     if (! file_exists($_CONF['path_log'] . 'error.log')) {
   992         $config->set('path_log', $path . 'logs/');
   993     }
   994     if (! file_exists($_CONF['path_language'] . $_CONF['language'] . '.php')) {
   995         $config->set('path_language', $path . 'language/');
   996     }
   997     if (! file_exists($_CONF['backup_path'])) {
   998         $config->set('backup_path', $path . 'backups/');
   999     }
  1000     if (! file_exists($_CONF['path_data'])) {
  1001         $config->set('path_data', $path . 'data/');
  1002     }
  1003     if ((! $_CONF['have_pear']) &&
  1004             (! file_exists($_CONF['path_pear'] . 'PEAR.php'))) {
  1005         $config->set('path_pear', $path . 'system/pear/');
  1006     }
  1007 
  1008     if (! file_exists($_CONF['path_html'] . 'lib-common.php')) {
  1009         $config->set('path_html', $path_html);
  1010     }
  1011     if (! file_exists($_CONF['path_themes'] . $_CONF['theme']
  1012                                             . '/header.thtml')) {
  1013         $config->set('path_themes', $path_html . 'layout/');
  1014 
  1015         if (! file_exists($path_html . 'layout/' . $_CONF['theme']
  1016                                                  . '/header.thtml')) {
  1017             $config->set('theme', 'professional');
  1018         }
  1019     }
  1020     if (! file_exists($_CONF['path_images'] . 'articles')) {
  1021         $config->set('path_images', $path_html . 'images/');
  1022     }
  1023     if (substr($_CONF['rdf_file'], strlen($path_html)) != $path_html) {
  1024         // this may not be correct but neither was the old value apparently ...
  1025         $config->set('rdf_file', $path_html . 'backend/geeklog.rss');
  1026     }
  1027 
  1028     if (! empty($site_url) && ($_CONF['site_url'] != $site_url)) {
  1029         $config->set('site_url', $site_url);
  1030 
  1031         // if we had to fix the site's URL, chances are that cookie domain
  1032         // and path are also wrong and the user won't be able to log in
  1033         $config->set('cookiedomain', '');
  1034         $config->set('cookie_path', '/');
  1035     }
  1036     if (! empty($site_admin_url) &&
  1037             ($_CONF['site_admin_url'] != $site_admin_url)) {
  1038         $config->set('site_admin_url', $site_admin_url);
  1039     }
  1040 }
  1041 
  1042 /**
  1043  * Helper function: Derive 'path_html' from __FILE__
  1044  *
  1045  */
  1046 function INST_getHtmlPath()
  1047 {
  1048     $path = str_replace('\\', '/', __FILE__);
  1049     $path = str_replace('//', '/', $path);
  1050     $parts = explode('/', $path);
  1051     $num_parts = count($parts);
  1052     if (($num_parts < 3) || ($parts[$num_parts - 1] != 'lib-install.php')) {
  1053         die('Fatal error - can not figure out my own path');
  1054     }
  1055 
  1056     return implode('/', array_slice($parts, 0, $num_parts - 3)) . '/';
  1057 }
  1058 
  1059 /**
  1060  * Helper function: Derive path of the 'admin' directory from __FILE__
  1061  *
  1062  */
  1063 function INST_getAdminPath()
  1064 {
  1065     $path = str_replace('\\', '/', __FILE__);
  1066     $path = str_replace('//', '/', $path);
  1067     $parts = explode('/', $path);
  1068     $num_parts = count($parts);
  1069     if (($num_parts < 3) || ($parts[$num_parts - 1] != 'lib-install.php')) {
  1070         die('Fatal error - can not figure out my own path');
  1071     }
  1072 
  1073     return implode('/', array_slice($parts, 0, $num_parts - 2)) . '/';
  1074 }
  1075 
  1076 /**
  1077  * Helper function: Derive 'site_url' from PHP_SELF
  1078  *
  1079  */
  1080 function INST_getSiteUrl()
  1081 {
  1082     $url = str_replace('//', '/', $_SERVER['PHP_SELF']);
  1083     $parts = explode('/', $url);
  1084     $num_parts = count($parts);
  1085     if (($num_parts < 3) || (substr($parts[$num_parts - 1], -4) != '.php')) {
  1086         die('Fatal error - can not figure out my own URL');
  1087     }
  1088 
  1089     $url = implode('/', array_slice($parts, 0, $num_parts - 3));
  1090 
  1091     return 'http://' . $_SERVER['HTTP_HOST'] . $url;
  1092 }
  1093 
  1094 /**
  1095  * Helper function: Derive 'site_admin_url' from PHP_SELF
  1096  *
  1097  */
  1098 function INST_getSiteAdminUrl()
  1099 {
  1100     $url = str_replace('//', '/', $_SERVER['PHP_SELF']);
  1101     $parts = explode('/', $url);
  1102     $num_parts = count($parts);
  1103     if (($num_parts < 3) || (substr($parts[$num_parts - 1], -4) != '.php')) {
  1104         die('Fatal error - can not figure out my own URL');
  1105     }
  1106 
  1107     $url = implode('/', array_slice($parts, 0, $num_parts - 2));
  1108 
  1109     return 'http://' . $_SERVER['HTTP_HOST'] . $url;
  1110 }
  1111 
  1112 /**
  1113  * Get name of the install language file to use
  1114  *
  1115  * @return  string      language file name (without the extension)
  1116  *
  1117  */
  1118 function INST_getLanguage()
  1119 {
  1120     $language = 'english';
  1121     if (isset($_POST['language'])) {
  1122         $lng = $_POST['language'];
  1123     } elseif (isset($_GET['language'])) {
  1124         $lng = $_GET['language'];
  1125     } elseif (isset($_COOKIE['language'])) {
  1126         // Okay, so the name of the language cookie is configurable, so it
  1127         // may not be named 'language' after all. Still worth a try ...
  1128         $lng = $_COOKIE['language'];
  1129     } else {
  1130         $lng = $language;
  1131     }
  1132 
  1133     // sanitize value and check for file
  1134     $lng = preg_replace('/[^a-z0-9\-_]/', '', $lng);
  1135     if (!empty($lng) && is_file('language/' . $lng . '.php')) {
  1136         $language = $lng;
  1137     }
  1138 
  1139     return $language;
  1140 }
  1141 
  1142 /**
  1143 * Set Geeklog version number in siteconfig.php and in the database
  1144 *
  1145 * @param   string  $siteconfig_path    path to siteconfig.php
  1146 * @return  void
  1147 *
  1148 */
  1149 function INST_setVersion($siteconfig_path)
  1150 {
  1151     global $_TABLES, $LANG_INSTALL;
  1152 
  1153     $siteconfig_file = fopen($siteconfig_path, 'rb');
  1154     $siteconfig_data = fread($siteconfig_file, filesize($siteconfig_path));
  1155     fclose($siteconfig_file);
  1156 
  1157     $siteconfig_data = preg_replace
  1158             (
  1159              '/define\s*\(\'VERSION\',[^;]*;/',
  1160              "define('VERSION', '" . VERSION . "');",
  1161              $siteconfig_data
  1162             );
  1163 
  1164     $siteconfig_file = @fopen($siteconfig_path, 'wb');
  1165     if (! fwrite($siteconfig_file, $siteconfig_data)) {
  1166         exit($LANG_INSTALL[26] . ' ' . $LANG_INSTALL[28]);
  1167     }
  1168     fclose($siteconfig_file);
  1169 
  1170     // for the database version, get rid of any appendices ('sr1' etc.)
  1171     $version = VERSION;
  1172     $v = explode('.', VERSION);
  1173     if (count($v) == 3) {
  1174         $v[2] = (int) $v[2];
  1175         $version = implode('.', $v);
  1176     }
  1177     $version = addslashes($version);
  1178 
  1179     DB_change($_TABLES['vars'], 'value', $version, 'name', 'database_version');
  1180 }
  1181 
  1182 /**
  1183 * Filter path value for junk and injections
  1184 *
  1185 * @param    string  $path   a path on the file system
  1186 * @return   string          filtered path value
  1187 *
  1188 */
  1189 function INST_sanitizePath($path)
  1190 {
  1191     $path = strip_tags($path);
  1192     $path = str_replace(array('"', "'"), '', $path);
  1193     $path = str_replace('..', '', $path);
  1194 
  1195     return $path;
  1196 }
  1197 
  1198 ?>