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

Documentation generated on Sun, 08 Feb 2009 22:01:07 +0100 by phpDocumentor 1.4.1