Source for file install.php

Documentation is available at install.php

  1. <?php
  2. /**
  3.  * PLUGIN INSTALLER for Contenido >= 4.8
  4.  *
  5.  * @author      Martin Horwath (horwath@dayside.net)
  6.  * @author      Paul Sauer (contenido@saueronline.de)
  7.  * @author      Murat Purc (murat@purc.de)
  8.  * @version     0.5
  9.  * @since       File available since contenido release >= 4.8
  10.  * @package     Contenido
  11.  * @subpackage  Plugin installer
  12.  *
  13.  *
  14.  *  {@internal 
  15.  *      26.09.2004 - Martin Horwath <horwath@dayside.net> - maybe initial release
  16.  *      10.10.2005 - unknown - unknown changes
  17.  *      15.02.2006 - Paul Sauer <contenido@saueronline.de> - unknown changes
  18.  *      12.09.2006 - Murat Purc <murat@purc.de> - some modifications, like simple templating
  19.  *      26.10.2008 - Murat Purc <murat@purc.de> - XHTML, cleanup, etc.
  20.  *  }}}
  21.  */
  22.  
  23.  
  24. if (!defined("CON_FRAMEWORK")) {
  25.     define("CON_FRAMEWORK"true);
  26. }
  27.  
  28. ####################################################################################################
  29. # Initialization
  30.  
  31. $contenido_path '../../';
  32.  
  33. // include security class and check request variables
  34. include_once ($contenido_path 'classes/class.security.php');
  35. Contenido_Security::checkRequests();
  36.  
  37. $cfg['debug']['installer'false;
  38. $bCheckTableStatus true;
  39.  
  40. include_once($contenido_path 'includes/startup.php');
  41.  
  42. // set url path to backend
  43. $aPath parse_url($cfg['path']['contenido_fullhtml']);
  44. $contenido_html $aPath['path'];
  45.  
  46. cInclude('includes''functions.general.php');
  47.  
  48. $cfg["debug"]["backend_exectime"]["fullstart"getmicrotime();
  49.  
  50. cInclude('includes''functions.i18n.php');
  51. cInclude('includes''functions.api.php');
  52. cInclude('includes''functions.general.php');
  53. cInclude('includes''functions.database.php');
  54. cInclude('includes''functions.str.php');
  55.  
  56. cInclude('classes''class.xml.php');
  57. cInclude('classes''class.navigation.php');
  58. cInclude('classes''class.template.php');
  59. cInclude('classes''class.backend.php');
  60. cInclude('classes''class.notification.php');
  61. cInclude('classes''class.area.php');
  62. cInclude('classes''class.action.php');
  63. cInclude('classes''class.layout.php');
  64. cInclude('classes''class.treeitem.php');
  65. cInclude('classes''class.user.php');
  66. cInclude('classes''class.group.php');
  67. cInclude('classes''class.cat.php');
  68. cInclude('classes''class.client.php');
  69. cInclude('classes''class.inuse.php');
  70. cInclude('classes''class.table.php');
  71.  
  72. page_open(array('sess' => 'Contenido_Session''auth' => 'Contenido_Challenge_Crypt_Auth''perm' => 'Contenido_Perm'));
  73.  
  74. i18nInit($cfg['path']['contenido'$cfg['path']['locale']$belang);
  75. cInclude('includes''cfg_language_de.inc.php');
  76.  
  77. // overwrite error reporting
  78. error_reporting (E_ALL E_NOTICE);
  79.  
  80. ####################################################################################################
  81. # Some installer classes
  82.  
  83. // @todo: Outsource the classes below!
  84.  
  85. class DB_Upgrade extends DB_Contenido {/*donut*/}
  86.  
  87. /**
  88.  * Plugin setup interface, each plugin installer class should implement this
  89.  * interface.
  90.  *
  91.  * @author      Murat Purc (murat@purc.de)
  92.  * @package     Contenido
  93.  * @subpackage  PluginInstaller
  94.  */
  95. interface IPluginSetup {
  96.     public function install();
  97.     public function upgrade();
  98.     public function uninstall();
  99. }
  100.  
  101. /**
  102.  * Abstract plugin setup base class, each plugin installer should extend this
  103.  * class.
  104.  *
  105.  * @author      Murat Purc (murat@purc.de)
  106.  * @package     Contenido
  107.  * @subpackage  PluginInstaller
  108.  */
  109. abstract class PluginSetupAbstract {
  110.     protected $_cfg;
  111.     protected $_db;
  112.     public function __construct(){
  113.         $this->_cfg = $GLOBALS['cfg']// damn globals
  114.         $this->_db  = new DB_Contenido();
  115.     }
  116. }
  117.  
  118. /**
  119.  * Final plugin setup factory class
  120.  *
  121.  * @author      Murat Purc (murat@purc.de)
  122.  * @package     Contenido
  123.  * @subpackage  PluginInstaller
  124.  */
  125. final class PluginSetupFactory {
  126.     public static function getInstaller($className{
  127.         if (!class_exists($className)) {
  128.             throw new Exception('PluginSetupFactory:getInstaller() Class "' $className '" doesn\'t exists, include classfile before calling factory');
  129.         }
  130.         return new $className();
  131.     }
  132. }
  133.  
  134.  
  135. ####################################################################################################
  136. # Main installer process
  137.  
  138. $cfg["debug"]["backend_exectime"]["start"getmicrotime();
  139.  
  140. // include mr installer
  141. plugin_include('mod_rewrite''classes/class.modrewriteinstaller.php');
  142.  
  143. // instanzen der db_contenido
  144. $db  new DB_Contenido;
  145. $db2 new DB_Contenido;
  146.  
  147. // mr installer instance
  148. $oPluginInstaller PluginSetupFactory::getInstaller('ModRewriteInstaller');
  149.  
  150. $data['top']         'Plugin "Advanced Mod Rewrite" installer';
  151. $data['content']     '';
  152. $data['bottom']      '';
  153. $data['body_bottom''';
  154.  
  155. $sBackendLink '<br /><a href="' $contenido_html '?contenido=' $contenido '" title="Switch to backend">Switch to Contenido backend</a>' "\n";
  156.  
  157. if ($bCheckTableStatus{
  158.     $aRequiredFields array(
  159.         "idplugin""name""version""author""idinternal""url",
  160.         "status""description""install""uninstall""date"
  161.     );
  162.  
  163. //    $sRequiredTable = "DROP TABLE " . $cfg['tab']['plugins'] . ";
  164.     $sRequiredTable "RENAME TABLE " $cfg['tab']['plugins'" TO " $cfg['tab']['plugins'"_" date('Ymd'";
  165.                       CREATE TABLE " $cfg['tab']['plugins'" (
  166.                           idplugin INT(10) NOT NULL default '0',
  167.                           name VARCHAR(60) default NULL,
  168.                           version VARCHAR(10) NOT NULL default '0',
  169.                           author VARCHAR(60) default NULL,
  170.                           idinternal VARCHAR(32) NOT NULL default '0',
  171.                           url TEXT,
  172.                           status INT(10) NOT NULL default '0',
  173.                           description TEXT,
  174.                           install TEXT,
  175.                           uninstall TEXT,
  176.                           date DATETIME NOT NULL default '0000-00-00 00:00:00',
  177.                           PRIMARY KEY (idplugin)
  178.                       ) TYPE=MyISAM;";
  179.     // now we check if the plugin table has the right format...
  180.     msg("Checking status " $cfg['tab']['plugins']);
  181.     $aPluginTableMeta $db->metadata($cfg['tab']['plugins']);
  182.  
  183.     foreach ($aPluginTableMeta as $key{
  184.         if (!in_array($key['name']$aRequiredFields)) {
  185.             msg($key['name'" (this key can be deleted)""unused key");
  186.         else {
  187.             $aAvailableKeys[$key['name'];
  188.         }
  189.         $aFoundKeys[$key['name'];
  190.     }
  191.     foreach ($aRequiredFields as $key{
  192.         if (!in_array($key$aFoundKeys)) {
  193.             msg($key " (this key must be added)""missing key");
  194.             $aMissingKeys[$key;
  195.         }
  196.     }
  197.     unset ($aFoundKeys$key);
  198.     // available elements in table are stored in array -> $aAvailableKeys;
  199.     // missing elements in table are stored in array -> $aMissingKeys;
  200.     // this is a possible way to handle new versions of plugin installer
  201.     // since this is initial release the table will be dropped and recreated
  202.     // when a missing element is found.
  203.     if (count($aMissingKeys0{
  204.         $sSqlData   remove_remarks($sRequiredTable);
  205.         $aSqlPieces split_sql_file($sSqlData';');
  206.         msg(count($aSqlPieces" queries""Executing:");
  207.         foreach ($aSqlPieces as $sqlinit{
  208.             $db->query($sqlinit);
  209.             msg($sqlinit);
  210.         }
  211.     else {
  212.         msg("ok");
  213.     }
  214. }
  215.  
  216. // con_sequence update
  217.  
  218.  
  219. if ($installsql file_get_contents('install.sql')) {
  220.     // get info from sql file
  221.     if (preg_match ("/####(.*)####/i"$installsql$pinfo)) {
  222.         $pinfo explode (";"$pinfo[1]);
  223.         // take some nice names easier to work with...
  224.         $pname       $pinfo[0];
  225.         $pversion    $pinfo[1];
  226.         $pauthor     $pinfo[2];
  227.         $pinternalid $pinfo[3];
  228.  
  229.         unset($pinfo);
  230.         // first show info
  231.         $data['content'.= "<div class='col1'>Plugin Name:</div><div class='col2'>" $pname "</div><br class='clear' />\n";
  232.         $data['content'.= "<div class='col1'>Plugin Version:</div><div class='col2'>" $pversion "</div><br class='clear' />\n";
  233.         $data['content'.= "<div class='col1'>Author:</div><div class='col2'>" $pauthor "</div><br class='clear' />\n";
  234.         $data['content'.= "<div class='col1'>Internal ID:</div><div class='col2'>" $pinternalid "</div><br class='clear' />\n";
  235.         $data['content'.= "<br />\n";
  236.  
  237.         // the user don't need this info...
  238.         $installsql preg_replace ("/####(.*)####/i"""$installsql);
  239.  
  240.         $pstatus true;
  241.     else {
  242.         $data['content'.= "Info missing. First line of install.sql should include following line:<br />";
  243.         $data['content'.= "<strong>####NAME;VERSION;AUTHOR;INTERNAL_ID####</strong><br />";
  244.         $data['content'.= "No further action takes place<br />";
  245.  
  246.         $pstatus false;
  247.     }
  248.  
  249.     // check if idinternal is allready available in table
  250.     $sql "SELECT * FROM " $cfg["tab"]["plugins"" WHERE idinternal='" $pinternalid "';";
  251.     $db->query($sql);
  252.     if ($db->next_record()) {
  253.         $mode     "update";
  254.         $message .= "Plugin with this internal id allready exists in table.<br />\n";
  255.         if ($pversion == $db->f('version')) {
  256.             $message .= "This version is allready installed.<br />\n";
  257.             $mode     "uninstall";
  258.         else {
  259.             $message .= "Switching to upgrade mode.<br />\n";
  260.         }
  261.         $pluginid $db->f('idplugin');
  262.     else {
  263.         $mode     "install";
  264.         $message .= "No plugin with this internal id exists in table.<br />\n";
  265.         $pluginid false;
  266.     }
  267.  
  268.     if (!$install && !$uninstall{
  269.         $data['content'.= "<br />" $message;
  270.     }
  271.  
  272.     if (!$install && $mode == "update"{
  273.         $data['content'.= "<br /><a class=\"submit\" href=\"$PHP_SELF?install=1&amp;contenido=$contenido\" title=\"Update plugin\">Update $pname $pversion</a><br />\n";
  274.     }
  275.  
  276.     if (!$install && $mode == "install"{
  277.         $data['content'.= "<br /><a class=\"submit\" href=\"$PHP_SELF?install=1&amp;contenido=$contenido\" title=\"Install plugin\">Install $pname $pversion</a><br />\n";
  278.     }
  279.  
  280.     if (!$uninstall && $mode == "uninstall"{
  281.         $data['content'.= "<br /><a class=\"submit\" href=\"$PHP_SELF?uninstall=1&amp;contenido=$contenido\" title=\"UnInstall plugin\">UnInstall $pname $pversion</a><br />\n";
  282.         $data['content'.= "<br /><br /><strong>Note:</strong><br />";
  283.         $data['content'.= "The UnInstaller will only remove plugin related entries from database (plugins table). Any done changes on directories or files must be reset manually.<br />";
  284.     }
  285.  
  286.     if ($uninstall && $pluginid{
  287.         $sql "SELECT uninstall FROM " $cfg["tab"]["plugins"" WHERE idplugin='" $pluginid "'";
  288.         msg($sql);
  289.         $db->query($sql);
  290.         $db->next_record();
  291.  
  292.         $uninstallsql $db->f('uninstall');
  293.         $sSqlData     remove_remarks($uninstallsql);
  294.         $aSqlPieces   split_sql_file($sSqlData';');
  295.  
  296.         msg(count($aSqlPieces)." queries""Executing:");
  297.         foreach ($aSqlPieces as $sqlinit{
  298.             $db->query($sqlinit);
  299.             msg($sqlinit);
  300.         }
  301.  
  302.         $oPluginInstaller->uninstall();
  303.  
  304.         $data['content'.= "<br /><strong>Uninstall complete.</strong><br />\n";
  305.     }
  306.  
  307.     if ($pstatus && $install{
  308.         if ($mode == "install"// insert all data from install.sql
  309.             $pluginid $db->nextid($cfg["tab"]["plugins"])// get next free id using phplib method
  310.  
  311.             $PID 100 $pluginid// generate !PID! replacement
  312.             $replace array('!PREFIX!' => $cfg['sql']['sqlprefix']'!PID!' => $PID);
  313.  
  314.             $installsql strtr($installsql$replace);
  315.  
  316.             $sql "INSERT INTO " $cfg["tab"]["plugins"" (idplugin,name,`version`,author,idinternal,`status`,`date`) VALUES ('" $pluginid "','" $pname "','" $pversion "','" $pauthor "','" $pinternalid "','0','" date("Y-m-d H:i:s""');";
  317.             $uninstallsql "DELETE FROM " $cfg["tab"]["plugins"" WHERE idplugin='" $pluginid "';\r\n";
  318.             msg($sql"Insert statement for plugin: ");
  319.             $db->query($sql);
  320.  
  321.             msg ($installsql"Install query:");
  322.  
  323.             $sSqlData   remove_remarks($installsql);
  324.             $aSqlPieces split_sql_file($sSqlData';');
  325.             msg(count($aSqlPieces" queries""Executing:");
  326.             foreach ($aSqlPieces as $sqlinit{
  327.                 // $sqlinit = strtr($sqlinit, $replace);
  328.                 // create uninstall.sql for each insert entry
  329.                 if (preg_match("/INSERT\s+INTO\s+(.*)\s+VALUES\s*\([´\"'\s]*(\d+)/i"$sqlinit$tmpsql)) {
  330.                     $tmpidname $db->metadata(trim(str_replace("`"""$tmpsql[1])));
  331.                     $tmpidname $tmpidname[0]['name'];
  332.                     $uninstallsql "DELETE FROM " trim($tmpsql[1]" WHERE " $tmpidname "='" trim($tmpsql[2]"';\r\n" $uninstallsql;
  333.                 }
  334.  
  335.                 $db->query($sqlinit);
  336.                 msg($sqlinit);
  337.             }
  338.  
  339.             if ($uninstallsqlfile file_get_contents('uninstall.sql')) {
  340.                 $uninstallsqlfile remove_remarks($uninstallsqlfile)// remove all comments
  341.  
  342.                 $uninstallsql .= strtr($uninstallsqlfile$replace)// add to generated sql
  343.                 $data['content'.= "I found uninstall.sql in " dirname(__FILE__"<br />Statements added to uninstall query.<br />\n";
  344.             }
  345.  
  346.             msg ($uninstallsql"Uninstall query:");
  347.  
  348.             $sql "UPDATE " $cfg["tab"]["plugins"" SET install=0x" bin2hex($installsql", uninstall=0x" bin2hex($uninstallsql" WHERE (idplugin='" $pluginid "');";
  349.             msg($sql"un/install statements stored");
  350.             $db->query($sql);
  351.  
  352.             $oPluginInstaller->install();
  353.  
  354.             $data['content'.= "<br /><strong>Install complete.</strong><br />\n";
  355.         }
  356.  
  357.         if ($mode == "update"{
  358.             $sql  "UPDATE " $cfg["tab"]["plugins"" SET\n";
  359.             $sql .= " version = '" $pversion "'\n";
  360.             $sql .= "WHERE (idplugin='" $pluginid "');";
  361.             msg($sql"Store new plugin version: ");
  362.             $db->query($sql);
  363.             if ($updatesqlfile @file_get_contents('update.sql')) {
  364.                 $sql "SELECT uninstall FROM " $cfg["tab"]["plugins"" WHERE idplugin='" $pluginid "'";
  365.                 msg($sql"Getting stored uninstall statements: ");
  366.                 $db->query($sql);
  367.                 $db->next_record();
  368.  
  369.                 $uninstallsql  $db->f('uninstall');
  370.                 $updatesqlfile remove_remarks($updatesqlfile)// remove all comments
  371.  
  372.                 $data['content'.= "I found update.sql in " dirname(__FILE__"<br />\n";
  373.  
  374.                 $PID 100 $pluginid// generate !PID! replacement
  375.                 $replace array('!PREFIX!' => $cfg['sql']['sqlprefix']'!PID!' => $PID);
  376.                 $updatesql .= strtr($updatesqlfile$replace)// add to generated sql
  377.  
  378.                 $aSqlPieces split_sql_file($updatesql';');
  379.                 msg(count($aSqlPieces" queries""Executing:");
  380.                 foreach ($aSqlPieces as $sqlinit{
  381.                     // $sqlinit = strtr($sqlinit, $replace);
  382.                     // create uninstall.sql for each insert entry
  383.                     if (preg_match("/INSERT\s+INTO\s+(.*)\s+VALUES\s*\([´\"'\s]*(\d+)/i"$sqlinit$tmpsql)) {
  384.                         $tmpidname    $db->metadata(trim(str_replace("`"""$tmpsql[1])));
  385.                         $tmpidname    $tmpidname[0]['name'];
  386.                         $uninstallsql "DELETE FROM " trim($tmpsql[1]" WHERE " $tmpidname "='" trim($tmpsql[2]"';\r\n" $uninstallsql;
  387.                     else if (preg_match("/REPLACE \s+INTO\s+(.*)\s+VALUES\s*\([´\"'\s]*(\d+)/i"$sqlinit$tmpsql)) {
  388.                         $tmpidname    $db->metadata(trim(str_replace("`"""$tmpsql[1])));
  389.                         $tmpidname    $tmpidname[0]['name'];
  390.                         $uninstallsql "DELETE FROM " trim($tmpsql[1]" WHERE " $tmpidname "='" trim($tmpsql[2]"';\r\n" $uninstallsql;
  391.                     }
  392.  
  393.                     $db->query($sqlinit);
  394.                     msg($sqlinit);
  395.                 }
  396.                 $sql "UPDATE " $cfg["tab"]["plugins"" SET uninstall = 0x" bin2hex($uninstallsql" WHERE (idplugin='" $pluginid "');";
  397.                 msg($sql"New uninstall statements stored: ");
  398.                 $db->query($sql);
  399.             }
  400.  
  401.             $oPluginInstaller->upgrade();
  402.  
  403.             $data['content'.= "<br /><strong>Update complete.</strong><br />\n";
  404.         }
  405.  
  406.         // con_sequence update
  407.         updateSequence();
  408.     }
  409. else {
  410.     $data['content'.= "Sorry i found no install.sql in " dirname(__FILE__"<br />\n";
  411. }
  412.  
  413.  
  414. $data['bottom']      .= $sBackendLink;
  415. $data['body_bottom']  getDebugMsg();
  416.  
  417. $cfg["debug"]["backend_exectime"]["end"getmicrotime();
  418.  
  419. if ($cfg["debug"]["rendering"== true{
  420.     $data['body_bottom'.= "Rendering this page took: " ($cfg["debug"]["backend_exectime"]["end"$cfg["debug"]["backend_exectime"]["start"]" seconds<br />";
  421.     $data['body_bottom'.= "Building the complete page took: " ($cfg["debug"]["backend_exectime"]["end"$cfg["debug"]["backend_exectime"]["fullstart"]" seconds<br />";
  422.  
  423.     if (function_exists("memory_get_usage")) {
  424.         $data['body_bottom'.= "Include memory usage: " human_readable_size(memory_get_usage($cfg["debug"]["oldmemusage"]"<br />";
  425.         $data['body_bottom'.= "Complete memory usage: " human_readable_size(memory_get_usage()) "<br />";
  426.     }
  427. }
  428.  
  429.  
  430. page_close();
  431.  
  432.  
  433. ####################################################################################################
  434. ##### Output
  435.  
  436. echo <<<HTML
  437. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  438.     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  439. <html xmlns="http://www.w3.org/1999/xhtml">
  440. <head>
  441.     <title>Plugin installer</title>
  442.     <meta http-equiv="expires" content="0" />
  443.     <meta http-equiv="cache-control" content="no-cache" />
  444.     <meta http-equiv="pragma" content="no-cache" />
  445.     <link rel="stylesheet" type="text/css" href="{$contenido_html}styles/contenido.css" />
  446.     <style type="text/css"><!--
  447.     body {font-family:verdana; font-size:12px;}
  448.     #wrap {width:750px; margin:50px auto; border:1px solid #b3b3b3;}
  449.     #head {width:100%; border-bottom:1px solid black;}
  450.     #content_top {background-color:#e2e2e2; font-weight:bold; padding:5px 0 5px 10px; border-bottom:1px solid #b3b3b3;}
  451.     #content {padding:10px;}
  452.     a:link, a:visited, a:hover {color:#0060b1; font-size:12px;}
  453.     a:hover {text-decoration:underline;}
  454.     a.submit, a.submit:hover {display:block; height:18px; padding-left:20px;}
  455.     a.submit {background:transparent url({$contenido_html}images/submit.gif) no-repeat;}
  456.     a.submit:hover {background:transparent url({$contenido_html}images/submit_hover.gif) no-repeat;}
  457.     .col1 {width:10em; float:left; padding-bottom:0.3em;}
  458.     .col2 {width:auto; float:left; padding-bottom:0.3em;}
  459.     .clear {clear:both; font-size:0px; line-height:0px; }
  460.     --></style>
  461. </head>
  462. <body>
  463.  
  464. <div id="wrap">
  465.     <div id="head">
  466.       <a id="head_logo" href="{$contenido_html}?contenido=$contenido" title="Switch to Contenido backend">
  467.         <img src="{$contenido_html}images/conlogo.gif" alt="Contenido Logo" /></a>
  468.     </div>
  469.     <br class="clear" />
  470.  
  471.     <div id="content_top">
  472.         {$data['top']}
  473.     </div>
  474.  
  475.     <div id="content">
  476.         <form name="frmPluginInstall" id="frmPluginInstall" method="post" action="$PHP_SELF">
  477.         <input type="hidden" name="contenido" value="$contenido" />
  478.         {$data['content']}
  479.         {$data['bottom']}
  480.         </form>
  481.         {$data['body_bottom']}
  482.     </div>
  483. </div>
  484.  
  485. </body>
  486. </html>
  487. HTML;
  488.  
  489.  
  490. ####################################################################################################
  491. ##### Functions
  492.  
  493. // some functions to work with...
  494. /**
  495.  * removes '# blabla...' from the mysql_dump.
  496.  * This function was originally developed for phpbb 2.01
  497.  * (C) 2001 The phpBB Group http://www.phpbb.com
  498.  *
  499.  * @return string input_without_#
  500.  */
  501. function remove_remarks($sql{
  502.     $lines explode("\n"$sql);
  503.     // try to keep mem. use down
  504.     $sql "";
  505.  
  506.     $linecount count($lines);
  507.     $output "";
  508.  
  509.     for ($i 0$i $linecount$i++{
  510.         if (($i != ($linecount 1)) || (strlen($lines[$i]0)) {
  511.             $output .= ($lines[$i][0!= "#")  $lines[$i]."\n" "\n";
  512.  
  513.             // Trading a bit of speed for lower mem. use here.
  514.             $lines[$i"";
  515.         }
  516.     }
  517.     return $output;
  518. }
  519.  
  520. /**
  521.  * Splits sql- statements into handy pieces.
  522.  * This function was original developed for the phpbb 2.01
  523.  * (C) 2001 The phpBB Group http://www.phpbb.com
  524.  *
  525.  * @return array sql_pieces
  526.  */
  527. function split_sql_file($sql$delimiter{
  528.   // Split up our string into "possible" SQL statements.
  529.   $tokens explode($delimiter$sql);
  530.   // try to save mem.
  531.   $sql "";
  532.   $output array();
  533.   // we don't actually care about the matches preg gives us.
  534.   $matches array();
  535.   // this is faster than calling count($oktens) every time thru the loop.
  536.   $token_count count($tokens);
  537.   for ($i 0$i $token_count$i++{
  538.     // Dont wanna add an empty string as the last thing in the array.
  539.     if (($i != ($token_count 1)) || (strlen($tokens[$i0))) {
  540.       // This is the total number of single quotes in the token.
  541.       $total_quotes preg_match_all("/'/"$tokens[$i]$matches);
  542.       // Counts single quotes that are preceded by an odd number of backslashes,
  543.       // which means they're escaped quotes.
  544.       $escaped_quotes preg_match_all("/(?<!\\\\)(\\\\\\\\)*\\\\'/"$tokens[$i]$matches);
  545.  
  546.       $unescaped_quotes $total_quotes $escaped_quotes;
  547.       // If the number of unescaped quotes is even, then the delimiter did NOT occur inside a string literal.
  548.       if (($unescaped_quotes 2== 0{
  549.         // It's a complete sql statement.
  550.         $output[$tokens[$i];
  551.         // save memory.
  552.         $tokens[$i"";
  553.       else {
  554.         // incomplete sql statement. keep adding tokens until we have a complete one.
  555.         // $temp will hold what we have so far.
  556.         $temp $tokens[$i$delimiter;
  557.         // save memory..
  558.         $tokens[$i"";
  559.         // Do we have a complete statement yet?
  560.         $complete_stmt false;
  561.  
  562.         for ($j $i 1(!$complete_stmt && ($j $token_count))$j++{
  563.           // This is the total number of single quotes in the token.
  564.           $total_quotes preg_match_all("/'/"$tokens[$j]$matches);
  565.           // Counts single quotes that are preceded by an odd number of backslashes,
  566.           // which means theyre escaped quotes.
  567.           $escaped_quotes preg_match_all("/(?<!\\\\)(\\\\\\\\)*\\\\'/"$tokens[$j]$matches);
  568.  
  569.           $unescaped_quotes $total_quotes $escaped_quotes;
  570.  
  571.           if (($unescaped_quotes 2== 1{
  572.             // odd number of unescaped quotes. In combination with the previous incomplete
  573.             // statement(s), we now have a complete statement. (2 odds always make an even)
  574.             $output[$temp $tokens[$j];
  575.             // save memory.
  576.             $tokens[$j"";
  577.             $temp "";
  578.             // exit the loop.
  579.             $complete_stmt true;
  580.             // make sure the outer loop continues at the right point.
  581.             $i $j;
  582.           else {
  583.             // even number of unescaped quotes. We still dont have a complete statement.
  584.             // (1 odd and 1 even always make an odd)
  585.             $temp .= $tokens[$j$delimiter;
  586.             // save memory.
  587.             $tokens[$j"";
  588.           }
  589.         // for..
  590.       // else
  591.     }
  592.   }
  593.   return $output;
  594. }
  595.  
  596.  
  597. // simple function to update con_sequence
  598. function updateSequence($table false{
  599.     global $db$cfg;
  600.     if (!$table{
  601.         $sql "SHOW TABLES";
  602.         $db->query($sql);
  603.         while ($db->next_record()) {
  604.             dbUpdateSequence($cfg['sql']['sqlprefix'"_sequence"$db->f(0));
  605.         }
  606.     else {
  607.         dbUpdateSequence($cfg['sql']['sqlprefix'"_sequence"$table);
  608.     }
  609. }
  610.  
  611.  
  612. // read out next free id * deprecated
  613. function getSequenceId($table{
  614.     global $db2$cfg;
  615.     $sql "SELECT nextid FROM " $cfg['sql']['sqlprefix'"_sequence" " where seq_name = '$table'";
  616.     $db2->query($sql);
  617.     if ($db2->next_record()) {
  618.         return ($db2->f("nextid"1);
  619.     else {
  620.         msg($table"missing in " $cfg['sql']['sqlprefix'"_sequence");
  621.         return 0;
  622.     }
  623. }
  624.  
  625.  
  626. // debug functions
  627. function msg($value$info false{
  628.     global $cfg;
  629.     if (trim($cfg["debug"]["messages"]== ""$cfg["debug"]["messages""<br /><strong>DEBUG:</strong>";
  630.     if (!$cfg["debug"]["installer"]{
  631.         return;
  632.     }
  633.     if ($info{
  634.         $cfg["debug"]["messages".= "<strong>$info</strong> -> ";
  635.     }
  636.     if (is_array($value)) {
  637.         ob_start();
  638.         print_r($value);
  639.         $output ob_get_contents();
  640.         ob_end_clean();
  641.         $cfg["debug"]["messages".= "<pre>" htmlspecialchars($output"</pre>";
  642.     else {
  643.         $cfg["debug"]["messages".= htmlspecialchars($value"<br />";
  644.     }
  645. }
  646.  
  647. function getDebugMsg({
  648.     global $cfg;
  649.     if ($cfg["debug"]["installer"]{
  650.         return "<div style=\"font-family: Verdana, Arial, Helvetica, Sans-Serif; font-size: 11px; color: #000000\">"
  651.             . $cfg["debug"]["messages"]
  652.             . "</div>";
  653.     else {
  654.         return '';
  655.     }
  656. }
  657.  
  658.  
  659. /**
  660.  * isWriteable:
  661.  * Checks if a specific file is writeable. Includes a PHP 4.0.4
  662.  * workaround where is_writable doesn't return a value of type
  663.  * boolean. Also clears the stat cache and checks if the file
  664.  * exists.
  665.  *
  666.  * Copied from /setup/lib/functions.filesystem.php
  667.  *
  668.  * @param $file string    Path to the file, accepts absolute and relative files
  669.  * @return boolean true if the file exists and is writeable, false otherwise
  670.  */
  671. function isWriteable($file{
  672.     clearstatcache();
  673.     if (!file_exists($file)) {
  674.         return false;
  675.     }
  676.  
  677.     $bStatus is_writable($file);
  678.     /* PHP 4.0.4 workaround */
  679.     settype($bStatus"boolean");
  680.  
  681.     return $bStatus;
  682. }
  683.  
  684.  
  685. function copyFile($source$destination$backupName=null{
  686.     global $cfg;
  687.  
  688.     // check source and destination, allow filesystem processes only inside htdocs
  689.     if (strpos($source$cfg['path']['frontend']=== false{
  690.         return false;
  691.     elseif (strpos($destination$cfg['path']['frontend']=== false{
  692.         return false;
  693.     elseif (isset($backupName&& strpos($backupName$cfg['path']['frontend']=== false{
  694.         return false;
  695.     }
  696.  
  697.     if ($backupName !== null{
  698.         if (!rename($destination$backupName)) {
  699.             return false;
  700.         }
  701.     }
  702.  
  703.     if (!copy($source$destination '.bak')) {
  704.         return false;
  705.     }
  706.  
  707.     return true;
  708. }

Documentation generated on Tue, 25 Nov 2008 22:07:48 +0100 by phpDocumentor 1.4.1