]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/upgrade.php
loadsave: check if the dumped file will be accessible from outside.
[SourceForge/phpwiki.git] / lib / upgrade.php
1 <?php //-*-php-*-
2 rcs_id('$Id: upgrade.php,v 1.26 2004-10-14 19:19:34 rurban Exp $');
3
4 /*
5  Copyright 2004 $ThePhpWikiProgrammingTeam
6
7  This file is part of PhpWiki.
8
9  PhpWiki is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13
14  PhpWiki is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with PhpWiki; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24
25 /**
26  * Upgrade the WikiDB and config settings after installing a new 
27  * PhpWiki upgrade.
28  * Status: experimental, no queries for verification yet, no db update,
29  *         no merge conflict
30  *
31  * Installation on an existing PhpWiki database needs some 
32  * additional worksteps. Each step will require multiple pages.
33  *
34  * This is the plan:
35  *  1. Check for new or changed database schema and update it 
36  *     according to some predefined upgrade tables. (medium)
37  *  2. Check for new or changed (localized) pgsrc/ pages and ask 
38  *     for upgrading these. Check timestamps, upgrade silently or 
39  *     show diffs if existing. Overwrite or merge (easy)
40  *  3. Check for new or changed or deprecated index.php/config.ini settings
41  *     and help in upgrading these. (hard)
42  *  3a Convert old-style index.php into config/config.ini. (easy)
43  *  4. Check for changed plugin invocation arguments. (hard)
44  *  5. Check for changed theme variables. (hard)
45  *  6. Convert the automatic update to a class-based multi-page 
46  *     version. (hard)
47
48  * TODO: overwrite=1 link on edit conflicts at end of page to overwrite all.
49  *
50  * @author: Reini Urban
51  */
52 require_once("lib/loadsave.php");
53 //define('DBADMIN_USER','rurban');
54 //define('DBADMIN_PASSWD','');
55
56 /**
57  * TODO: check for the pgsrc_version number, not the revision mtime only
58  */
59 function doPgsrcUpdate(&$request,$pagename,$path,$filename) {
60     $dbi = $request->getDbh(); 
61     $page = $dbi->getPage($pagename);
62     if ($page->exists()) {
63         // check mtime: update automatically if pgsrc is newer
64         $rev = $page->getCurrentRevision();
65         $page_mtime = $rev->get('mtime');
66         $data  = implode("", file($path."/".$filename));
67         if (($parts = ParseMimeifiedPages($data))) {
68             usort($parts, 'SortByPageVersion');
69             reset($parts);
70             $pageinfo = $parts[0];
71             $stat  = stat($path."/".$filename);
72             $new_mtime = @$pageinfo['versiondata']['mtime'];
73             if (!$new_mtime)
74                 $new_mtime = @$pageinfo['versiondata']['lastmodified'];
75             if (!$new_mtime)
76                 $new_mtime = @$pageinfo['pagedata']['date'];
77             if (!$new_mtime)
78                 $new_mtime = $stat[9];
79             if ($new_mtime > $page_mtime) {
80                 echo "$path/$pagename: ",_("newer than the existing page."),
81                     _(" replace "),"($new_mtime &gt; $page_mtime)","<br />\n";
82                 LoadAny($request,$path."/".$filename);
83                 echo "<br />\n";
84             } else {
85                 echo "$path/$pagename: ",_("older than the existing page."),
86                     _(" skipped"),".<br />\n";
87             }
88         } else {
89             echo "$path/$pagename: ",("unknown format."),
90                     _(" skipped"),".<br />\n";
91         }
92     } else {
93         echo sprintf(_("%s does not exist"),$pagename),"<br />\n";
94         LoadAny($request,$path."/".$filename);
95         echo "<br />\n";
96     }
97 }
98
99 /** need the english filename (required precondition: urlencode == urldecode)
100  *  returns the plugin name.
101  */ 
102 function isActionPage($filename) {
103     static $special = array("DebugInfo"         => "_BackendInfo",
104                             "PhpWikiRecentChanges" => "RssFeed",
105                             "ProjectSummary"    => "RssFeed",
106                             "RecentReleases"    => "RssFeed",
107                             );
108     $base = preg_replace("/\..{1,4}$/","",basename($filename));
109     if (isset($special[$base])) return $special[$base];
110     if (FindFile("lib/plugin/".$base.".php",true)) return $base;
111     else return false;
112 }
113
114 function CheckActionPageUpdate(&$request) {
115     echo "<h3>",_("check for necessary ActionPage updates"),"</h3>\n";
116     $dbi = $request->getDbh(); 
117     $path = FindFile('pgsrc');
118     $pgsrc = new fileSet($path);
119     // most actionpages have the same name as the plugin
120     $loc_path = FindLocalizedFile('pgsrc');
121     foreach ($pgsrc->getFiles() as $filename) {
122         if (substr($filename,-1,1) == '~') continue;
123         $pagename = urldecode($filename);
124         if (isActionPage($filename)) {
125             $translation = gettext($pagename);
126             if ($translation == $pagename)
127                 doPgsrcUpdate($request, $pagename, $path, $filename);
128             elseif (FindLocalizedFile('pgsrc/'.urlencode($translation),1))
129                 doPgsrcUpdate($request, $translation, $loc_path, 
130                               urlencode($translation));
131             else
132                 doPgsrcUpdate($request, $pagename, $path, $filename);
133         }
134     }
135 }
136
137 // see loadsave.php for saving new pages.
138 function CheckPgsrcUpdate(&$request) {
139     echo "<h3>",_("check for necessary pgsrc updates"),"</h3>\n";
140     $dbi = $request->getDbh(); 
141     $path = FindLocalizedFile(WIKI_PGSRC);
142     $pgsrc = new fileSet($path);
143     // fixme: verification, ...
144     $isHomePage = false;
145     foreach ($pgsrc->getFiles() as $filename) {
146         if (substr($filename,-1,1) == '~') continue;
147         $pagename = urldecode($filename);
148         // don't ever update the HomePage
149         if (defined(HOME_PAGE))
150             if ($pagename == HOME_PAGE) $isHomePage = true;
151         else
152             if ($pagename == _("HomePage")) $isHomePage = true;
153         if ($pagename == "HomePage") $isHomePage = true;
154         if ($isHomePage) {
155             echo "$path/$pagename: ",_("always skip the HomePage."),
156                 _(" skipped"),".<br />\n";
157             $isHomePage = false;
158             continue;
159         }
160         if (!isActionPage($filename)) {
161             doPgsrcUpdate($request,$pagename,$path,$filename);
162         }
163     }
164     return;
165 }
166
167 /**
168  * TODO: Search table definition in appropriate schema
169  *       and create it.
170  * Supported: mysql and generic SQL, for ADODB and PearDB.
171  */
172 function installTable(&$dbh, $table, $backend_type) {
173     global $DBParams;
174     if (!in_array($DBParams['dbtype'],array('SQL','ADODB'))) return;
175     echo _("MISSING")," ... \n";
176     $backend = &$dbh->_backend->_dbh;
177     /*
178     $schema = findFile("schemas/${backend_type}.sql");
179     if (!$schema) {
180         echo "  ",_("FAILED"),": ",sprintf(_("no schema %s found"),"schemas/${backend_type}.sql")," ... <br />\n";
181         return false;
182     }
183     */
184     extract($dbh->_backend->_table_names);
185     $prefix = isset($DBParams['prefix']) ? $DBParams['prefix'] : '';
186     switch ($table) {
187     case 'session':
188         assert($session_tbl);
189         if ($backend_type == 'mysql') {
190             $dbh->genericSqlQuery("
191 CREATE TABLE $session_tbl (
192         sess_id         CHAR(32) NOT NULL DEFAULT '',
193         sess_data       BLOB NOT NULL,
194         sess_date       INT UNSIGNED NOT NULL,
195         sess_ip         CHAR(15) NOT NULL,
196         PRIMARY KEY (sess_id),
197         INDEX (sess_date)
198 )");
199         } else {
200             $dbh->genericSqlQuery("
201 CREATE TABLE $session_tbl (
202         sess_id         CHAR(32) NOT NULL DEFAULT '',
203         sess_data       ".($backend_type == 'pgsql'?'TEXT':'BLOB')." NOT NULL,
204         sess_date       INT,
205         sess_ip         CHAR(15) NOT NULL
206 )");
207             $dbh->genericSqlQuery("CREATE UNIQUE INDEX sess_id ON $session_tbl (sess_id)");
208         }
209         $dbh->genericSqlQuery("CREATE INDEX sess_date on session (sess_date)");
210         break;
211     case 'user':
212         $user_tbl = $prefix.'user';
213         if ($backend_type == 'mysql') {
214             $dbh->genericSqlQuery("
215 CREATE TABLE $user_tbl (
216         userid  CHAR(48) BINARY NOT NULL UNIQUE,
217         passwd  CHAR(48) BINARY DEFAULT '',
218         PRIMARY KEY (userid)
219 )");
220         } else {
221             $dbh->genericSqlQuery("
222 CREATE TABLE $user_tbl (
223         userid  CHAR(48) NOT NULL,
224         passwd  CHAR(48) DEFAULT ''
225 )");
226             $dbh->genericSqlQuery("CREATE UNIQUE INDEX userid ON $user_tbl (userid)");
227         }
228         break;
229     case 'pref':
230         $pref_tbl = $prefix.'pref';
231         if ($backend_type == 'mysql') {
232             $dbh->genericSqlQuery("
233 CREATE TABLE $pref_tbl (
234         userid  CHAR(48) BINARY NOT NULL UNIQUE,
235         prefs   TEXT NULL DEFAULT '',
236         PRIMARY KEY (userid)
237 )");
238         } else {
239             $dbh->genericSqlQuery("
240 CREATE TABLE $pref_tbl (
241         userid  CHAR(48) NOT NULL,
242         prefs   TEXT NULL DEFAULT '',
243 )");
244             $dbh->genericSqlQuery("CREATE UNIQUE INDEX userid ON $pref_tbl (userid)");
245         }
246         break;
247     case 'member':
248         $member_tbl = $prefix.'member';
249         if ($backend_type == 'mysql') {
250             $dbh->genericSqlQuery("
251 CREATE TABLE $member_tbl (
252         userid    CHAR(48) BINARY NOT NULL,
253         groupname CHAR(48) BINARY NOT NULL DEFAULT 'users',
254         INDEX (userid),
255         INDEX (groupname)
256 )");
257         } else {
258             $dbh->genericSqlQuery("
259 CREATE TABLE $member_tbl (
260         userid    CHAR(48) NOT NULL,
261         groupname CHAR(48) NOT NULL DEFAULT 'users',
262 )");
263             $dbh->genericSqlQuery("CREATE INDEX userid ON $member_tbl (userid)");
264             $dbh->genericSqlQuery("CREATE INDEX groupname ON $member_tbl (groupname)");
265         }
266         break;
267     case 'rating':
268         $rating_tbl = $prefix.'rating';
269         if ($backend_type == 'mysql') {
270             $dbh->genericSqlQuery("
271 CREATE TABLE $rating_tbl (
272         dimension INT(4) NOT NULL,
273         raterpage INT(11) NOT NULL,
274         rateepage INT(11) NOT NULL,
275         ratingvalue FLOAT NOT NULL,
276         rateeversion INT(11) NOT NULL,
277         tstamp TIMESTAMP(14) NOT NULL,
278         PRIMARY KEY (dimension, raterpage, rateepage)
279 )");
280         } else {
281             $dbh->genericSqlQuery("
282 CREATE TABLE $rating_tbl (
283         dimension INT(4) NOT NULL,
284         raterpage INT(11) NOT NULL,
285         rateepage INT(11) NOT NULL,
286         ratingvalue FLOAT NOT NULL,
287         rateeversion INT(11) NOT NULL,
288         tstamp TIMESTAMP(14) NOT NULL,
289 )");
290             $dbh->genericSqlQuery("CREATE UNIQUE INDEX rating ON $rating_tbl (dimension, raterpage, rateepage)");
291         }
292         break;
293     }
294     echo "  ",_("CREATED"),"<br />\n";
295 }
296
297 /**
298  * currently update only session, user, pref and member
299  * jeffs-hacks database api (around 1.3.2) later
300  *   people should export/import their pages if using that old versions.
301  */
302 function CheckDatabaseUpdate(&$request) {
303     global $DBParams, $DBAuthParams;
304     if (!in_array($DBParams['dbtype'], array('SQL','ADODB'))) return;
305     echo "<h3>",_("check for necessary database updates"),"</h3>\n";
306     if (defined('DBADMIN_USER') and DBADMIN_USER) {
307         // if need to connect as the root user, for alter permissions
308         $AdminParams = $DBParams;
309         if ($DBParams['dbtype'] == 'SQL')
310             $dsn = DB::parseDSN($AdminParams['dsn']);
311         else
312             $dsn = parseDSN($AdminParams['dsn']);
313         $AdminParams['dsn'] = sprintf("%s://%s:%s@%s/%s",
314                                       $dsn['phptype'],
315                                       DBADMIN_USER,
316                                       DBADMIN_PASSWD,
317                                       $dsn['hostspec'],
318                                       $dsn['database']);
319         $dbh = WikiDB::open($AdminParams);
320     } else {
321         $dbh = &$request->_dbi;
322     }
323     $tables = $dbh->_backend->listOfTables();
324     $backend_type = $dbh->_backend->backendType();
325     $prefix = isset($DBParams['prefix']) ? $DBParams['prefix'] : '';
326     foreach (explode(':','session:user:pref:member') as $table) {
327         echo sprintf(_("check for table %s"), $table)," ...";
328         if (!in_array($prefix.$table, $tables)) {
329             installTable($dbh, $table, $backend_type);
330         } else {
331             echo _("OK")," <br />\n";
332         }
333     }
334     $backend = &$dbh->_backend->_dbh;
335     // 1.3.8 added session.sess_ip
336     if (phpwiki_version() >= 1030.08 and USE_DB_SESSION and isset($request->_dbsession)) {
337         echo _("check for new session.sess_ip column")," ... ";
338         $database = $dbh->_backend->database();
339         assert(!empty($DBParams['db_session_table']));
340         $session_tbl = $prefix . $DBParams['db_session_table'];
341         $sess_fields = $dbh->_backend->listOfFields($database, $session_tbl);
342         if (!strstr(strtolower(join(':', $sess_fields)),"sess_ip")) {
343             // TODO: postgres test (should be able to add columns at the end, but not in between)
344             echo "<b>",_("ADDING"),"</b>"," ... ";              
345             $dbh->genericSqlQuery("ALTER TABLE $session_tbl ADD sess_ip CHAR(15) NOT NULL");
346             $dbh->genericSqlQuery("CREATE INDEX sess_date ON $session_tbl (sess_date)");
347         } else {
348             echo _("OK");
349         }
350         echo "<br />\n";
351     }
352     // 1.3.10 mysql requires page.id auto_increment
353     // mysql, mysqli or mysqlt
354     if (phpwiki_version() >= 1030.099 and substr($backend_type,0,5) == 'mysql') {
355         echo _("check for page.id auto_increment flag")," ...";
356         extract($dbh->_backend->_table_names);
357         assert(!empty($page_tbl));
358         $database = $dbh->_backend->database();
359         $fields = mysql_list_fields($database, $page_tbl, $dbh->_backend->connection());
360         $columns = mysql_num_fields($fields); 
361         for ($i = 0; $i < $columns; $i++) {
362             if (mysql_field_name($fields, $i) == 'id') {
363                 $flags = mysql_field_flags($fields, $i);
364                 //DONE: something was wrong with ADODB here.
365                 if (!strstr(strtolower($flags), "auto_increment")) {
366                     echo "<b>",_("ADDING"),"</b>"," ... ";
367                     // MODIFY col_def valid since mysql 3.22.16,
368                     // older mysql's need CHANGE old_col col_def
369                     $dbh->genericSqlQuery("ALTER TABLE $page_tbl CHANGE id id INT NOT NULL AUTO_INCREMENT");
370                     $fields = mysql_list_fields($database, $page_tbl);
371                     if (!strstr(strtolower(mysql_field_flags($fields, $i)), "auto_increment"))
372                         echo " <b><font color=\"red\">", _("FAILED"), "</font></b><br />\n";
373                     else     
374                         echo _("OK"), "<br />\n";
375                 } else {
376                     echo _("OK"), "<br />\n";                           
377                 }
378                 break;
379             }
380         }
381         mysql_free_result($fields);
382     }
383     // check for mysql 4.1.x/5.0.0a binary search problem.
384     //   http://bugs.mysql.com/bug.php?id=4398
385     // "select * from page where LOWER(pagename) like '%search%'" does not apply LOWER!
386     // confirmed for 4.1.0alpha,4.1.3-beta,5.0.0a; not yet tested for 4.1.2alpha,
387     // TODO: there's a known workaround, not yet applied. on windows only.
388     if (substr($backend_type,0,5) == 'mysql') {
389         echo _("check for mysql 4.1.x/5.0.0 binary search problem")," ...";
390         $result = mysql_query("SELECT VERSION()",$dbh->_backend->connection());
391         $row = mysql_fetch_row($result);
392         $mysql_version = $row[0];
393         $arr = explode('.',$mysql_version);
394         $version = (string)(($arr[0] * 100) + $arr[1]) . "." . (integer)$arr[2];
395         if ($version >= 401.0) {
396             $dbh->genericSqlQuery("ALTER TABLE $page_tbl CHANGE pagename pagename VARCHAR(100) NOT NULL;");
397             echo sprintf(_("version <em>%s</em> <b>FIXED</b>"), $mysql_version),"<br />\n";     
398         } else {
399             echo sprintf(_("version <em>%s</em> not affected"), $mysql_version),"<br />\n";
400         }
401     }
402     return;
403 }
404
405 function fixConfigIni($match, $new) {
406     $file = FindFile("config/config.ini");
407     $found = false;
408     if (is_writable($file)) {
409         $in = fopen($file,"rb");
410         $out = fopen($tmp = tempnam(FindFile("uploads"),"cfg"),"wb");
411         if (isWindows())
412             $tmp = str_replace("/","\\",$tmp);
413         while ($s = fgets($in)) {
414             if (preg_match($match, $s)) {
415                 $s = $new . (isWindows() ? "\r\n" : "\n");
416                 $found = true;
417             }
418             fputs($out, $s);
419         }
420         fclose($in);
421         fclose($out);
422         if (!$found) {
423             echo " <b><font color=\"red\">",_("FAILED"),"</font></b>: ",
424                 sprintf(_("%s not found"), $match);
425             unlink($out);
426         } else {
427             @unlink("$file.bak");
428             @rename($file,"$file.bak");
429             if (rename($tmp, $file))
430                 echo " <b>",_("FIXED"),"</b>";
431             else {
432                 echo " <b>",_("FAILED"),"</b>: ";
433                 sprintf(_("couldn't move %s to %s"), $tmp, $file);
434                 return false;
435             }
436         }
437         return $found;
438     } else {
439         echo " <b><font color=\"red\">",_("FAILED"),"</font></b>: ",
440             sprintf(_("%s is not writable"), $file);
441         return false;
442     }
443 }
444
445 function CheckConfigUpdate(&$request) {
446     echo "<h3>",_("check for necessary config updates"),"</h3>\n";
447     echo _("check for old CACHE_CONTROL = NONE")," ... ";
448     if (defined('CACHE_CONTROL') and CACHE_CONTROL == '') {
449         echo "<br />&nbsp;&nbsp;",_("CACHE_CONTROL is set to 'NONE', and must be changed to 'NO_CACHE'")," ...";
450         fixConfigIni("/^\s*CACHE_CONTROL\s*=\s*NONE/","CACHE_CONTROL = NO_CACHE");
451     } else {
452         echo _("OK");
453     }
454     echo "<br />\n";
455 }
456
457 /**
458  * TODO:
459  *
460  * Upgrade: Base class for multipage worksteps
461  * identify, validate, display options, next step
462  */
463 class Upgrade {
464 }
465
466 class Upgrade_CheckPgsrc extends Upgrade {
467 }
468
469 class Upgrade_CheckDatabaseUpdate extends Upgrade {
470 }
471
472 // TODO: At which step are we? 
473 // validate and do it again or go on with next step.
474
475 /** entry function from lib/main.php
476  */
477 function DoUpgrade($request) {
478
479     if (!$request->_user->isAdmin()) {
480         $request->_notAuthorized(WIKIAUTH_ADMIN);
481         $request->finish(
482                          HTML::div(array('class' => 'disabled-plugin'),
483                                    fmt("Upgrade disabled: user != isAdmin")));
484         return;
485     }
486
487     StartLoadDump($request, _("Upgrading this PhpWiki"));
488     CheckActionPageUpdate($request);
489     CheckDatabaseUpdate($request);
490     CheckPgsrcUpdate($request);
491     //CheckThemeUpdate($request);
492     CheckConfigUpdate($request);
493     EndLoadDump($request);
494 }
495
496
497 /**
498  $Log: not supported by cvs2svn $
499  Revision 1.25  2004/09/06 08:28:00  rurban
500  rename genericQuery to genericSqlQuery
501
502  Revision 1.24  2004/07/05 13:56:22  rurban
503  sqlite autoincrement fix
504
505  Revision 1.23  2004/07/04 10:28:06  rurban
506  DBADMIN_USER fix
507
508  Revision 1.22  2004/07/03 17:21:28  rurban
509  updated docs: submitted new mysql bugreport (#1491 did not fix it)
510
511  Revision 1.21  2004/07/03 16:51:05  rurban
512  optional DBADMIN_USER:DBADMIN_PASSWD for action=upgrade (if no ALTER permission)
513  added atomic mysql REPLACE for PearDB as in ADODB
514  fixed _lock_tables typo links => link
515  fixes unserialize ADODB bug in line 180
516
517  Revision 1.20  2004/07/03 14:48:18  rurban
518  Tested new mysql 4.1.3-beta: binary search bug as fixed.
519  => fixed action=upgrade,
520  => version check in PearDB also (as in ADODB)
521
522  Revision 1.19  2004/06/19 12:19:09  rurban
523  slightly improved docs
524
525  Revision 1.18  2004/06/19 11:47:17  rurban
526  added CheckConfigUpdate: CACHE_CONTROL = NONE => NO_CACHE
527
528  Revision 1.17  2004/06/17 11:31:50  rurban
529  check necessary localized actionpages
530
531  Revision 1.16  2004/06/16 10:38:58  rurban
532  Disallow refernces in calls if the declaration is a reference
533  ("allow_call_time_pass_reference clean").
534    PhpWiki is now allow_call_time_pass_reference = Off clean,
535    but several external libraries may not.
536    In detail these libs look to be affected (not tested):
537    * Pear_DB odbc
538    * adodb oracle
539
540  Revision 1.15  2004/06/07 19:50:40  rurban
541  add owner field to mimified dump
542
543  Revision 1.14  2004/06/07 18:38:18  rurban
544  added mysql 4.1.x search fix
545
546  Revision 1.13  2004/06/04 20:32:53  rurban
547  Several locale related improvements suggested by Pierrick Meignen
548  LDAP fix by John Cole
549  reanable admin check without ENABLE_PAGEPERM in the admin plugins
550
551  Revision 1.12  2004/05/18 13:59:15  rurban
552  rename simpleQuery to genericSqlQuery
553
554  Revision 1.11  2004/05/15 13:06:17  rurban
555  skip the HomePage, at first upgrade the ActionPages, then the database, then the rest
556
557  Revision 1.10  2004/05/15 01:19:41  rurban
558  upgrade prefix fix by Kai Krakow
559
560  Revision 1.9  2004/05/14 11:33:03  rurban
561  version updated to 1.3.11pre
562  upgrade stability fix
563
564  Revision 1.8  2004/05/12 10:49:55  rurban
565  require_once fix for those libs which are loaded before FileFinder and
566    its automatic include_path fix, and where require_once doesn't grok
567    dirname(__FILE__) != './lib'
568  upgrade fix with PearDB
569  navbar.tmpl: remove spaces for IE &nbsp; button alignment
570
571  Revision 1.7  2004/05/06 17:30:38  rurban
572  CategoryGroup: oops, dos2unix eol
573  improved phpwiki_version:
574    pre -= .0001 (1.3.10pre: 1030.099)
575    -p1 += .001 (1.3.9-p1: 1030.091)
576  improved InstallTable for mysql and generic SQL versions and all newer tables so far.
577  abstracted more ADODB/PearDB methods for action=upgrade stuff:
578    backend->backendType(), backend->database(),
579    backend->listOfFields(),
580    backend->listOfTables(),
581
582  Revision 1.6  2004/05/03 15:05:36  rurban
583  + table messages
584
585  Revision 1.4  2004/05/02 21:26:38  rurban
586  limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
587    because they will not survive db sessions, if too large.
588  extended action=upgrade
589  some WikiTranslation button work
590  revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
591  some temp. session debug statements
592
593  Revision 1.3  2004/04/29 22:33:30  rurban
594  fixed sf.net bug #943366 (Kai Krakow)
595    couldn't load localized url-undecoded pagenames
596
597  Revision 1.2  2004/03/12 15:48:07  rurban
598  fixed explodePageList: wrong sortby argument order in UnfoldSubpages
599  simplified lib/stdlib.php:explodePageList
600
601  */
602
603 // For emacs users
604 // Local Variables:
605 // mode: php
606 // tab-width: 8
607 // c-basic-offset: 4
608 // c-hanging-comment-ender-p: nil
609 // indent-tabs-mode: nil
610 // End:
611 ?>