]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/upgrade.php
Disallow refernces in calls if the declaration is a reference
[SourceForge/phpwiki.git] / lib / upgrade.php
1 <?php //-*-php-*-
2 rcs_id('$Id: upgrade.php,v 1.16 2004-06-16 10:38:58 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  * Installation on an existing PhpWiki database needs some 
31  * additional worksteps. Each step will require multiple pages.
32  *
33  * This is the plan:
34  *  1. Check for new or changed database schema and update it 
35  *     according to some predefined upgrade tables. (medium)
36  *  2. Check for new or changed (localized) pgsrc/ pages and ask 
37  *     for upgrading these. Check timestamps, upgrade silently or 
38  *     show diffs if existing. Overwrite or merge (easy)
39  *  3. Check for new or changed or deprecated index.php settings
40  *     and help in upgrading these. (hard)
41  *  4. Check for changed plugin invocation arguments. (hard)
42  *  5. Check for changed theme variables. (hard)
43  *
44  * @author: Reini Urban
45  */
46 require_once("lib/loadsave.php");
47
48 /**
49  * TODO: check for the pgsrc_version number, not the revision
50  */
51 function doPgsrcUpdate(&$request,$pagename,$path,$filename) {
52     $dbi = $request->getDbh(); 
53     $page = $dbi->getPage($pagename);
54     if ($page->exists()) {
55         // check mtime: update automatically if pgsrc is newer
56         $rev = $page->getCurrentRevision();
57         $page_mtime = $rev->get('mtime');
58         $data  = implode("", file($path."/".$filename));
59         if (($parts = ParseMimeifiedPages($data))) {
60             usort($parts, 'SortByPageVersion');
61             reset($parts);
62             $pageinfo = $parts[0];
63             $stat  = stat($path."/".$filename);
64             $new_mtime = @$pageinfo['versiondata']['mtime'];
65             if (!$new_mtime)
66                 $new_mtime = @$pageinfo['versiondata']['lastmodified'];
67             if (!$new_mtime)
68                 $new_mtime = @$pageinfo['pagedata']['date'];
69             if (!$new_mtime)
70                 $new_mtime = $stat[9];
71             if ($new_mtime > $page_mtime) {
72                 echo "$path/$pagename: ",_("newer than the existing page."),
73                     _(" replace "),"($new_mtime &gt; $page_mtime)","<br />\n";
74                 LoadAny($request,$path."/".$filename);
75                 echo "<br />\n";
76             } else {
77                 echo "$path/$pagename: ",_("older than the existing page."),
78                     _(" skipped"),".<br />\n";
79             }
80         } else {
81             echo "$path/$pagename: ",("unknown format."),
82                     _(" skipped"),".<br />\n";
83         }
84     } else {
85         echo sprintf(_("%s does not exist"),$pagename),"<br />\n";
86         LoadAny($request,$path."/".$filename);
87         echo "<br />\n";
88     }
89 }
90
91 /** need the english filename (required precondition: urlencode == urldecode)
92  *  returns the plugin name.
93  */ 
94 function isActionPage($filename) {
95     static $special = array("DebugInfo"         => "_BackendInfo",
96                             "PhpWikiRecentChanges" => "RssFeed",
97                             "ProjectSummary"    => "RssFeed",
98                             "RecentReleases"    => "RssFeed",
99                             );
100     $base = preg_replace("/\..{1,4}$/","",basename($filename));
101     if (isset($special[$base])) return $special[$base];
102     if (FindFile("lib/plugin/".$base.".php",true)) return $base;
103     else return false;
104 }
105
106 function CheckActionPageUpdate(&$request) {
107     echo "<h3>",_("check for necessary ActionPage updates"),"</h3>\n";
108     $dbi = $request->getDbh(); 
109     $path = FindFile('pgsrc');
110     $pgsrc = new fileSet($path);
111     // most actionpages have the same name as the plugin
112     foreach ($pgsrc->getFiles() as $filename) {
113         if (substr($filename,-1,1) == '~') continue;
114         $pagename = urldecode($filename);
115         if (isActionPage($filename)) {
116             doPgsrcUpdate($request, $pagename, $path, $filename);
117         }
118     }
119 }
120
121 // see loadsave.php for saving new pages.
122 function CheckPgsrcUpdate(&$request) {
123     echo "<h3>",_("check for necessary pgsrc updates"),"</h3>\n";
124     $dbi = $request->getDbh(); 
125     $path = FindLocalizedFile(WIKI_PGSRC);
126     $pgsrc = new fileSet($path);
127     // fixme: verification, ...
128     $isHomePage = false;
129     foreach ($pgsrc->getFiles() as $filename) {
130         if (substr($filename,-1,1) == '~') continue;
131         $pagename = urldecode($filename);
132         // don't ever update the HomePage
133         if (defined(HOME_PAGE))
134             if ($pagename == HOME_PAGE) $isHomePage = true;
135         else
136             if ($pagename == _("HomePage")) $isHomePage = true;
137         if ($pagename == "HomePage") $isHomePage = true;
138         if ($isHomePage) {
139             echo "$path/$pagename: ",_("always skip the HomePage."),
140                 _(" skipped"),".<br />\n";
141             $isHomePage = false;
142             continue;
143         }
144         if (!isActionPage($filename)) {
145             doPgsrcUpdate($request,$pagename,$path,$filename);
146         }
147     }
148     return;
149 }
150
151 /**
152  * TODO: Search table definition in appropriate schema
153  *       and create it.
154  * Supported: mysql and generic SQL, for ADODB and PearDB.
155  */
156 function installTable(&$dbh, $table, $backend_type) {
157     global $DBParams;
158     if (!in_array($DBParams['dbtype'],array('SQL','ADODB'))) return;
159     echo _("MISSING")," ... \n";
160     $backend = &$dbh->_backend->_dbh;
161     /*
162     $schema = findFile("schemas/${backend_type}.sql");
163     if (!$schema) {
164         echo "  ",_("FAILED"),": ",sprintf(_("no schema %s found"),"schemas/${backend_type}.sql")," ... <br />\n";
165         return false;
166     }
167     */
168     extract($dbh->_backend->_table_names);
169     $prefix = isset($DBParams['prefix']) ? $DBParams['prefix'] : '';
170     switch ($table) {
171     case 'session':
172         assert($session_tbl);
173         if ($backend_type == 'mysql') {
174             $dbh->genericQuery("
175 CREATE TABLE $session_tbl (
176         sess_id         CHAR(32) NOT NULL DEFAULT '',
177         sess_data       BLOB NOT NULL,
178         sess_date       INT UNSIGNED NOT NULL,
179         sess_ip         CHAR(15) NOT NULL,
180         PRIMARY KEY (sess_id),
181         INDEX (sess_date)
182 )");
183         } else {
184             $dbh->genericQuery("
185 CREATE TABLE $session_tbl (
186         sess_id         CHAR(32) NOT NULL DEFAULT '',
187         sess_data       ".($backend_type == 'pgsql'?'TEXT':'BLOB')." NOT NULL,
188         sess_date       INT,
189         sess_ip         CHAR(15) NOT NULL
190 )");
191             $dbh->genericQuery("CREATE UNIQUE INDEX sess_id ON $session_tbl (sess_id)");
192         }
193         $dbh->genericQuery("CREATE INDEX sess_date on session (sess_date)");
194         break;
195     case 'user':
196         $user_tbl = $prefix.'user';
197         if ($backend_type == 'mysql') {
198             $dbh->genericQuery("
199 CREATE TABLE $user_tbl (
200         userid  CHAR(48) BINARY NOT NULL UNIQUE,
201         passwd  CHAR(48) BINARY DEFAULT '',
202         PRIMARY KEY (userid)
203 )");
204         } else {
205             $dbh->genericQuery("
206 CREATE TABLE $user_tbl (
207         userid  CHAR(48) NOT NULL,
208         passwd  CHAR(48) DEFAULT ''
209 )");
210             $dbh->genericQuery("CREATE UNIQUE INDEX userid ON $user_tbl (userid)");
211         }
212         break;
213     case 'pref':
214         $pref_tbl = $prefix.'pref';
215         if ($backend_type == 'mysql') {
216             $dbh->genericQuery("
217 CREATE TABLE $pref_tbl (
218         userid  CHAR(48) BINARY NOT NULL UNIQUE,
219         prefs   TEXT NULL DEFAULT '',
220         PRIMARY KEY (userid)
221 )");
222         } else {
223             $dbh->genericQuery("
224 CREATE TABLE $pref_tbl (
225         userid  CHAR(48) NOT NULL,
226         prefs   TEXT NULL DEFAULT '',
227 )");
228             $dbh->genericQuery("CREATE UNIQUE INDEX userid ON $pref_tbl (userid)");
229         }
230         break;
231     case 'member':
232         $member_tbl = $prefix.'member';
233         if ($backend_type == 'mysql') {
234             $dbh->genericQuery("
235 CREATE TABLE $member_tbl (
236         userid    CHAR(48) BINARY NOT NULL,
237         groupname CHAR(48) BINARY NOT NULL DEFAULT 'users',
238         INDEX (userid),
239         INDEX (groupname)
240 )");
241         } else {
242             $dbh->genericQuery("
243 CREATE TABLE $member_tbl (
244         userid    CHAR(48) NOT NULL,
245         groupname CHAR(48) NOT NULL DEFAULT 'users',
246 )");
247             $dbh->genericQuery("CREATE INDEX userid ON $member_tbl (userid)");
248             $dbh->genericQuery("CREATE INDEX groupname ON $member_tbl (groupname)");
249         }
250         break;
251     case 'rating':
252         $rating_tbl = $prefix.'rating';
253         if ($backend_type == 'mysql') {
254             $dbh->genericQuery("
255 CREATE TABLE $rating_tbl (
256         dimension INT(4) NOT NULL,
257         raterpage INT(11) NOT NULL,
258         rateepage INT(11) NOT NULL,
259         ratingvalue FLOAT NOT NULL,
260         rateeversion INT(11) NOT NULL,
261         tstamp TIMESTAMP(14) NOT NULL,
262         PRIMARY KEY (dimension, raterpage, rateepage)
263 )");
264         } else {
265             $dbh->genericQuery("
266 CREATE TABLE $rating_tbl (
267         dimension INT(4) NOT NULL,
268         raterpage INT(11) NOT NULL,
269         rateepage INT(11) NOT NULL,
270         ratingvalue FLOAT NOT NULL,
271         rateeversion INT(11) NOT NULL,
272         tstamp TIMESTAMP(14) NOT NULL,
273 )");
274             $dbh->genericQuery("CREATE UNIQUE INDEX rating ON $rating_tbl (dimension, raterpage, rateepage)");
275         }
276         break;
277     }
278     echo "  ",_("CREATED"),"<br />\n";
279 }
280
281 /**
282  * currently update only session, user, pref and member
283  * jeffs-hacks database api (around 1.3.2) later
284  *   people should export/import their pages if using that old versions.
285  */
286 function CheckDatabaseUpdate($request) {
287     global $DBParams, $DBAuthParams;
288     if (!in_array($DBParams['dbtype'], array('SQL','ADODB'))) return;
289     echo "<h3>",_("check for necessary database updates"),"</h3>\n";
290     $dbh = &$request->_dbi;
291     $tables = $dbh->_backend->listOfTables();
292     $backend_type = $dbh->_backend->backendType();
293     $prefix = isset($DBParams['prefix']) ? $DBParams['prefix'] : '';
294     extract($dbh->_backend->_table_names);
295     foreach (explode(':','session:user:pref:member') as $table) {
296         echo sprintf(_("check for table %s"), $table)," ...";
297         if (!in_array($prefix.$table, $tables)) {
298             installTable($dbh, $table, $backend_type);
299         } else {
300             echo _("OK")," <br />\n";
301         }
302     }
303     $backend = &$dbh->_backend->_dbh;
304     // 1.3.8 added session.sess_ip
305     if (phpwiki_version() >= 1030.08 and USE_DB_SESSION and isset($request->_dbsession)) {
306         echo _("check for new session.sess_ip column")," ... ";
307         $database = $dbh->_backend->database();
308         assert(!empty($DBParams['db_session_table']));
309         $session_tbl = $prefix . $DBParams['db_session_table'];
310         $sess_fields = $dbh->_backend->listOfFields($database, $session_tbl);
311         if (!strstr(strtolower(join(':', $sess_fields)),"sess_ip")) {
312             echo "<b>",_("ADDING"),"</b>"," ... ";              
313             $dbh->genericQuery("ALTER TABLE $session_tbl ADD sess_ip CHAR(15) NOT NULL");
314         } else {
315             echo _("OK");
316         }
317         echo "<br />\n";
318     }
319     // 1.3.10 mysql requires page.id auto_increment
320     // mysql, mysqli or mysqlt
321     if (phpwiki_version() >= 1030.099 and substr($backend_type,0,5) == 'mysql') {
322         echo _("check for page.id auto_increment flag")," ...";
323         assert(!empty($page_tbl));
324         $database = $dbh->_backend->database();
325         $fields = mysql_list_fields($database, $page_tbl, $dbh->_backend->connection());
326         $columns = mysql_num_fields($fields); 
327         for ($i = 0; $i < $columns; $i++) {
328             if (mysql_field_name($fields, $i) == 'id') {
329                 $flags = mysql_field_flags($fields, $i);
330                 //FIXME: something wrong with ADODB here!
331                 if (!strstr(strtolower($flags),"auto_increment")) {
332                     echo "<b>",_("ADDING"),"</b>"," ... ";              
333                     // MODIFY col_def valid since mysql 3.22.16,
334                     // older mysql's need CHANGE old_col col_def
335                     $dbh->genericQuery("ALTER TABLE $page_tbl CHANGE id id INT NOT NULL AUTO_INCREMENT");
336                     $fields = mysql_list_fields($database, $page_tbl);
337                     if (!strstr(strtolower(mysql_field_flags($fields, $i)),"auto_increment"))
338                         echo " <b><font color=\"red\">",_("FAILED"),"</font></b><br />\n";
339                     else     
340                         echo _("OK"),"<br />\n";
341                 } else {
342                     echo _("OK"),"<br />\n";                            
343                 }
344                 break;
345             }
346         }
347         mysql_free_result($fields);
348     }
349     // check for mysql 4.1.x binary search bug
350     // http://bugs.mysql.com/bug.php?id=1491
351     // not yet tested for 4.1.2alpha, but confirmed for 4.1.0alpha
352     if (substr($backend_type,0,5) == 'mysql') {
353         echo _("check for mysql 4.1.x binary search bug")," ...";
354         $result = mysql_query("SELECT VERSION()",$dbh->_backend->connection());
355         $row = mysql_fetch_row($result);
356         $mysql_version = $row[0];
357         $arr = explode('.',$mysql_version);
358         $version = (string)(($arr[0] * 100) + $arr[1]) . "." . $arr[2];
359         if ($version > 410.0 and $version < 420.0) {
360             $dbh->genericQuery("ALTER TABLE $page_tbl CHANGE pagename pagename VARCHAR(100) NOT NULL;");
361             echo sprintf(_("version <em>%s</em> <b>FIXED</b>"), $mysql_version),"<br />\n";     
362         } else {
363             echo sprintf(_("version <em>%s</em> not affected"), $mysql_version),"<br />\n";     
364         }
365     }
366     return;
367 }
368
369 /**
370  * Upgrade: Base class for multipage worksteps
371  * identify, validate, display options, next step
372  */
373 class Upgrade {
374 }
375
376 class Upgrade_CheckPgsrc extends Upgrade {
377 }
378
379 class Upgrade_CheckDatabaseUpdate extends Upgrade {
380 }
381
382 // TODO: At which step are we? 
383 // validate and do it again or go on with next step.
384
385 /** entry function from lib/main.php
386  */
387 function DoUpgrade($request) {
388
389     if (!$request->_user->isAdmin()) {
390         $request->_notAuthorized(WIKIAUTH_ADMIN);
391         $request->finish(
392                          HTML::div(array('class' => 'disabled-plugin'),
393                                    fmt("Upgrade disabled: user != isAdmin")));
394         return;
395     }
396
397     StartLoadDump($request, _("Upgrading this PhpWiki"));
398     CheckActionPageUpdate($request);
399     CheckDatabaseUpdate($request);
400     CheckPgsrcUpdate($request);
401     //CheckThemeUpdate($request);
402     EndLoadDump($request);
403 }
404
405
406 /**
407  $Log: not supported by cvs2svn $
408  Revision 1.15  2004/06/07 19:50:40  rurban
409  add owner field to mimified dump
410
411  Revision 1.14  2004/06/07 18:38:18  rurban
412  added mysql 4.1.x search fix
413
414  Revision 1.13  2004/06/04 20:32:53  rurban
415  Several locale related improvements suggested by Pierrick Meignen
416  LDAP fix by John Cole
417  reanable admin check without ENABLE_PAGEPERM in the admin plugins
418
419  Revision 1.12  2004/05/18 13:59:15  rurban
420  rename simpleQuery to genericQuery
421
422  Revision 1.11  2004/05/15 13:06:17  rurban
423  skip the HomePage, at first upgrade the ActionPages, then the database, then the rest
424
425  Revision 1.10  2004/05/15 01:19:41  rurban
426  upgrade prefix fix by Kai Krakow
427
428  Revision 1.9  2004/05/14 11:33:03  rurban
429  version updated to 1.3.11pre
430  upgrade stability fix
431
432  Revision 1.8  2004/05/12 10:49:55  rurban
433  require_once fix for those libs which are loaded before FileFinder and
434    its automatic include_path fix, and where require_once doesn't grok
435    dirname(__FILE__) != './lib'
436  upgrade fix with PearDB
437  navbar.tmpl: remove spaces for IE &nbsp; button alignment
438
439  Revision 1.7  2004/05/06 17:30:38  rurban
440  CategoryGroup: oops, dos2unix eol
441  improved phpwiki_version:
442    pre -= .0001 (1.3.10pre: 1030.099)
443    -p1 += .001 (1.3.9-p1: 1030.091)
444  improved InstallTable for mysql and generic SQL versions and all newer tables so far.
445  abstracted more ADODB/PearDB methods for action=upgrade stuff:
446    backend->backendType(), backend->database(),
447    backend->listOfFields(),
448    backend->listOfTables(),
449
450  Revision 1.6  2004/05/03 15:05:36  rurban
451  + table messages
452
453  Revision 1.4  2004/05/02 21:26:38  rurban
454  limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
455    because they will not survive db sessions, if too large.
456  extended action=upgrade
457  some WikiTranslation button work
458  revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
459  some temp. session debug statements
460
461  Revision 1.3  2004/04/29 22:33:30  rurban
462  fixed sf.net bug #943366 (Kai Krakow)
463    couldn't load localized url-undecoded pagenames
464
465  Revision 1.2  2004/03/12 15:48:07  rurban
466  fixed explodePageList: wrong sortby argument order in UnfoldSubpages
467  simplified lib/stdlib.php:explodePageList
468
469  */
470
471 // For emacs users
472 // Local Variables:
473 // mode: php
474 // tab-width: 8
475 // c-basic-offset: 4
476 // c-hanging-comment-ender-p: nil
477 // indent-tabs-mode: nil
478 // End:
479 ?>