]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/loadsave.php
for older or CGI phps
[SourceForge/phpwiki.git] / lib / loadsave.php
1 <?php //-*-php-*-
2 rcs_id('$Id: loadsave.php,v 1.124 2004-10-04 23:44:28 rurban Exp $');
3
4 /*
5  Copyright 1999, 2000, 2001, 2002 $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 require_once("lib/ziplib.php");
26 require_once("lib/Template.php");
27
28 /**
29  * ignore fatal errors during dump
30  */
31 function _dump_error_handler(&$error) {
32     if ($error->isFatal()) {
33         $error->errno = E_USER_WARNING;
34         return true;
35     }
36     return true;         // Ignore error
37     /*
38     if (preg_match('/Plugin/', $error->errstr))
39         return true;
40     */
41     // let the message come through: call the remaining handlers:
42     // return false; 
43 }
44
45 function StartLoadDump(&$request, $title, $html = '')
46 {
47     // MockRequest is from the unit testsuite, a faked request. (may be cmd-line)
48     // We are silent on unittests.
49     if (isa($request,'MockRequest'))
50         return;
51     // FIXME: This is a hack. This really is the worst overall hack in phpwiki.
52     if ($html)
53         $html->pushContent('%BODY%');
54     $tmpl = Template('html', array('TITLE' => $title,
55                                    'HEADER' => $title,
56                                    'CONTENT' => $html ? $html : '%BODY%'));
57     echo ereg_replace('%BODY%.*', '', $tmpl->getExpansion($html));
58     // set marker for sendPageChangeNotification()
59     $GLOBALS['deferredPageChangeNotification'] = array();
60
61     /* Ignore fatals or warnings in any pagedumps (failing plugins). 
62      * WikiFunctionCb() fails with 4.0.6, works ok with 4.1.1 
63      */
64     if (!check_php_version(4,1) or (DEBUG & _DEBUG_VERBOSE)) return;
65     global $ErrorManager;
66     $ErrorManager->pushErrorHandler(new WikiFunctionCb('_dump_error_handler'));
67 }
68
69 function EndLoadDump(&$request)
70 {
71     if (isa($request,'MockRequest'))
72         return;
73     if (check_php_version(4,1)) {
74         global $ErrorManager;
75         $ErrorManager->popErrorHandler();
76     }
77     $action = $request->getArg('action');
78     $label = '';
79     switch ($action) {
80     case 'zip':        $label = _("ZIP files of database"); break;
81     case 'dumpserial': $label = _("Dump to directory"); break;
82     case 'upload':     $label = _("Upload File"); break;
83     case 'loadfile':   $label = _("Load File"); break;
84     case 'upgrade':    $label = _("Upgrade"); break;
85     case 'dumphtml': 
86     case 'ziphtml':    $label = _("Dump pages as XHTML"); break;
87     }
88     if ($label) $label = str_replace(" ","_",$label);
89     if ($action == 'browse') // loading virgin 
90         $pagelink = WikiLink(HOME_PAGE);
91     else
92         $pagelink = WikiLink(new WikiPageName(_("PhpWikiAdministration"),false,$label));
93     // do deferred sendPageChangeNotification()
94     if (!empty($GLOBALS['deferredPageChangeNotification'])) {
95         $pages = $all_emails = $all_users = array();
96         foreach ($GLOBALS['deferredPageChangeNotification'] as $p) {
97             list($pagename, $emails, $userids) = $p;
98             $pages[] = $pagename;
99             $all_emails = array_unique(array_merge($all_emails, $emails));
100             $all_users = array_unique(array_merge($all_users, $userids));
101         }
102         $editedby = sprintf(_("Edited by: %s"), $request->_userid);
103         $content = "Loaded the following pages:\n" . join("\n", $pages);
104         if (mail(join(',',$all_emails),"[".WIKI_NAME."] "._("LoadDump"), 
105                  _("LoadDump")."\n".
106                  $editedby."\n\n".
107                  $content))
108             trigger_error(sprintf(_("PageChange Notification sent to %s"),
109                                   join(',',$all_users)), E_USER_NOTICE);
110         else
111             trigger_error(sprintf(_("PageChange Notification Error: Couldn't send to %s"),
112                                   join(',',$all_users)), E_USER_WARNING);
113         unset($pages);
114         unset($all_emails);
115         unset($all_users);
116     }
117     unset($GLOBALS['deferredPageChangeNotification']);
118
119     PrintXML(HTML::p(HTML::strong(_("Complete."))),
120              HTML::p(fmt("Return to %s", $pagelink)));
121     echo "</body></html>\n";
122 }
123
124
125 ////////////////////////////////////////////////////////////////
126 //
127 //  Functions for dumping.
128 //
129 ////////////////////////////////////////////////////////////////
130
131 /**
132  * For reference see:
133  * http://www.nacs.uci.edu/indiv/ehood/MIME/2045/rfc2045.html
134  * http://www.faqs.org/rfcs/rfc2045.html
135  * (RFC 1521 has been superceeded by RFC 2045 & others).
136  *
137  * Also see http://www.faqs.org/rfcs/rfc2822.html
138  */
139 function MailifyPage ($page, $nversions = 1)
140 {
141     $current = $page->getCurrentRevision();
142     $head = '';
143
144     if (STRICT_MAILABLE_PAGEDUMPS) {
145         $from = defined('SERVER_ADMIN') ? SERVER_ADMIN : 'foo@bar';
146         //This is for unix mailbox format: (not RFC (2)822)
147         // $head .= "From $from  " . CTime(time()) . "\r\n";
148         $head .= "Subject: " . rawurlencode($page->getName()) . "\r\n";
149         $head .= "From: $from (PhpWiki)\r\n";
150         // RFC 2822 requires only a Date: and originator (From:)
151         // field, however the obsolete standard RFC 822 also
152         // requires a destination field.
153         $head .= "To: $from (PhpWiki)\r\n";
154     }
155     $head .= "Date: " . Rfc2822DateTime($current->get('mtime')) . "\r\n";
156     $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n",
157                      PHPWIKI_VERSION);
158
159     // This should just be entered by hand (or by script?)
160     // in the actual pgsrc files, since only they should have
161     // RCS ids.
162     //$head .= "X-Rcs-Id: \$Id\$\r\n";
163
164     $iter = $page->getAllRevisions();
165     $parts = array();
166     while ($revision = $iter->next()) {
167         $parts[] = MimeifyPageRevision($revision);
168         if ($nversions > 0 && count($parts) >= $nversions)
169             break;
170     }
171     if (count($parts) > 1)
172         return $head . MimeMultipart($parts);
173     assert($parts);
174     return $head . $parts[0];
175 }
176
177 /***
178  * Compute filename to used for storing contents of a wiki page.
179  *
180  * Basically we do a rawurlencode() which encodes everything except
181  * ASCII alphanumerics and '.', '-', and '_'.
182  *
183  * But we also want to encode leading dots to avoid filenames like
184  * '.', and '..'. (Also, there's no point in generating "hidden" file
185  * names, like '.foo'.)
186  *
187  * @param $pagename string Pagename.
188  * @return string Filename for page.
189  */
190 function FilenameForPage ($pagename)
191 {
192     $enc = rawurlencode($pagename);
193     return preg_replace('/^\./', '%2e', $enc);
194 }
195
196 /**
197  * The main() function which generates a zip archive of a PhpWiki.
198  *
199  * If $include_archive is false, only the current version of each page
200  * is included in the zip file; otherwise all archived versions are
201  * included as well.
202  */
203 function MakeWikiZip (&$request)
204 {
205     if ($request->getArg('include') == 'all') {
206         $zipname         = WIKI_NAME . _("FullDump") . date('Ymd-Hi') . '.zip';
207         $include_archive = true;
208     }
209     else {
210         $zipname         = WIKI_NAME . _("LatestSnapshot") . date('Ymd-Hi') . '.zip';
211         $include_archive = false;
212     }
213
214
215     $zip = new ZipWriter("Created by PhpWiki " . PHPWIKI_VERSION, $zipname);
216
217     /* ignore fatals in plugins */
218     if (check_php_version(4,1)) {
219         global $ErrorManager;
220         $ErrorManager->pushErrorHandler(new WikiFunctionCb('_dump_error_handler'));
221     }
222
223     $dbi = $request->getDbh();
224     $thispage = $request->getArg('pagename'); // for "Return to ..."
225     if ($exclude = $request->getArg('exclude')) {   // exclude which pagenames
226         $excludeList = explodePageList($exclude); 
227     } else {
228         $excludeList = array();
229     }
230     if ($whichpages = $request->getArg('pages')) {  // which pagenames
231         if ($whichpages == '[]') // current page
232             $whichpages = $thispage;
233         $pages = new WikiDB_Array_PageIterator(explodePageList($whichpages));
234     } else {
235         $pages = $dbi->getAllPages();
236     }
237     $request_args = $request->args;
238     
239     while ($page = $pages->next()) {
240         $request->args = $request_args; // some plugins might change them (esp. on POST)
241         if (! $request->getArg('start_debug'))
242             @set_time_limit(30); // Reset watchdog
243         else    
244             @set_time_limit(240);
245
246         $current = $page->getCurrentRevision();
247         if ($current->getVersion() == 0)
248             continue;
249
250         $pagename = $page->getName();
251         $wpn = new WikiPageName($pagename);
252         if (!$wpn->isValid())
253             continue;
254         if (in_array($page->getName(), $excludeList)) {
255             continue;
256         }
257
258         $attrib = array('mtime'    => $current->get('mtime'),
259                         'is_ascii' => 1);
260         if ($page->get('locked'))
261             $attrib['write_protected'] = 1;
262
263         if ($include_archive)
264             $content = MailifyPage($page, 0);
265         else
266             $content = MailifyPage($page);
267
268         $zip->addRegularFile( FilenameForPage($pagename),
269                               $content, $attrib);
270     }
271     $zip->finish();
272     if (check_php_version(4,1)) {
273         $ErrorManager->popErrorHandler();
274     }
275 }
276
277 function DumpToDir (&$request)
278 {
279     $directory = $request->getArg('directory');
280     if (empty($directory))
281         $directory = DEFAULT_DUMP_DIR; // See lib/plugin/WikiForm.php:87
282     if (empty($directory))
283         $request->finish(_("You must specify a directory to dump to"));
284
285     // see if we can access the directory the user wants us to use
286     if (! file_exists($directory)) {
287         if (! mkdir($directory, 0755))
288             $request->finish(fmt("Cannot create directory '%s'", $directory));
289         else
290             $html = HTML::p(fmt("Created directory '%s' for the page dump...",
291                                 $directory));
292     } else {
293         $html = HTML::p(fmt("Using directory '%s'", $directory));
294     }
295
296     StartLoadDump($request, _("Dumping Pages"), $html);
297
298     $dbi = $request->getDbh();
299     $thispage = $request->getArg('pagename'); // for "Return to ..."
300     if ($exclude = $request->getArg('exclude')) {   // exclude which pagenames
301         $excludeList = explodePageList($exclude); 
302     } else {
303         $excludeList = array();
304     }
305     if ($whichpages = $request->getArg('pages')) {  // which pagenames
306         if ($whichpages == '[]') // current page
307             $whichpages = $thispage;
308         $pages = new WikiDB_Array_PageIterator(explodePageList($whichpages));
309     } else {
310         $pages = $dbi->getAllPages();
311     }
312
313     $request_args = $request->args;
314     
315     while ($page = $pages->next()) {
316         $request->args = $request_args; // some plugins might change them (esp. on POST)
317         if (! $request->getArg('start_debug'))
318             @set_time_limit(30); // Reset watchdog.
319         else    
320             @set_time_limit(240);
321
322         $pagename = $page->getName();
323         if (!isa($request,'MockRequest')) {
324             PrintXML(HTML::br(), $pagename, ' ... ');
325             flush();
326         }
327
328         if (in_array($pagename, $excludeList)) {
329             if (!isa($request,'MockRequest')) {
330                 PrintXML(_("Skipped."));
331                 flush();
332             }
333             continue;
334         }
335         $filename = FilenameForPage($pagename);
336         $msg = HTML();
337         if($page->getName() != $filename) {
338             $msg->pushContent(HTML::small(fmt("saved as %s", $filename)),
339                               " ... ");
340         }
341
342         if ($request->getArg('include') == 'all')
343             $data = MailifyPage($page, 0);
344         else
345             $data = MailifyPage($page);
346
347         if ( !($fd = fopen("$directory/$filename", "wb")) ) {
348             $msg->pushContent(HTML::strong(fmt("couldn't open file '%s' for writing",
349                                                "$directory/$filename")));
350             $request->finish($msg);
351         }
352
353         $num = fwrite($fd, $data, strlen($data));
354         $msg->pushContent(HTML::small(fmt("%s bytes written", $num)));
355         if (!isa($request,'MockRequest')) {
356             PrintXML($msg);
357             flush();
358         }
359         assert($num == strlen($data));
360         fclose($fd);
361     }
362
363     EndLoadDump($request);
364 }
365
366 /**
367  * Dump all pages as XHTML to a directory, as pagename.html.
368  * Copies all used css files to the directory, all used images to a 
369  * "images" subdirectory, and all used buttons to a "images/buttons" subdirectory.
370  * The webserver must have write permissions to these directories. 
371  *   chown httpd HTML_DUMP_DIR; chmod u+rwx HTML_DUMP_DIR 
372  * should be enough.
373  *
374  * @param string directory (optional) path to dump to. Default: HTML_DUMP_DIR
375  * @param string pages     (optional) Comma-seperated of glob-style pagenames to dump
376  * @param string exclude   (optional) Comma-seperated of glob-style pagenames to exclude
377  */
378 function DumpHtmlToDir (&$request)
379 {
380     $directory = $request->getArg('directory');
381     if (empty($directory))
382         $directory = HTML_DUMP_DIR; // See lib/plugin/WikiForm.php:87
383     if (empty($directory))
384         $request->finish(_("You must specify a directory to dump to"));
385
386     // see if we can access the directory the user wants us to use
387     if (! file_exists($directory)) {
388         if (! mkdir($directory, 0755))
389             $request->finish(fmt("Cannot create directory '%s'", $directory));
390         else
391             $html = HTML::p(fmt("Created directory '%s' for the page dump...",
392                                 $directory));
393     } else {
394         $html = HTML::p(fmt("Using directory '%s'", $directory));
395     }
396
397     StartLoadDump($request, _("Dumping Pages"), $html);
398     $thispage = $request->getArg('pagename'); // for "Return to ..."
399
400     $dbi = $request->getDbh();
401     if ($exclude = $request->getArg('exclude')) {   // exclude which pagenames
402         $excludeList = explodePageList($exclude); 
403     } else {
404         $excludeList = array();
405     }
406     if ($whichpages = $request->getArg('pages')) {  // which pagenames
407         if ($whichpages == '[]') // current page
408             $whichpages = $thispage;
409         $pages = new WikiDB_Array_PageIterator(explodePageList($whichpages));
410     } else {
411         $pages = $dbi->getAllPages();
412     }
413
414     global $WikiTheme;
415     if (defined('HTML_DUMP_SUFFIX'))
416         $WikiTheme->HTML_DUMP_SUFFIX = HTML_DUMP_SUFFIX;
417     $WikiTheme->DUMP_MODE = 'HTML';
418     $request_args = $request->args;
419     
420     while ($page = $pages->next()) {
421         $request->args = $request_args; // some plugins might change them (esp. on POST)
422         if (! $request->getArg('start_debug'))
423             @set_time_limit(30); // Reset watchdog.
424         else    
425             @set_time_limit(240);
426           
427         $pagename = $page->getName();
428         if (!isa($request,'MockRequest')) {
429             PrintXML(HTML::br(), $pagename, ' ... ');
430             flush();
431         }
432         if (in_array($pagename, $excludeList)) {
433             if (!isa($request,'MockRequest')) {
434                 PrintXML(_("Skipped."));
435                 flush();
436             }
437             continue;
438         }
439
440         $request->setArg('pagename', $pagename); // Template::_basepage fix
441         $filename = FilenameForPage($pagename) . $WikiTheme->HTML_DUMP_SUFFIX;
442         $msg = HTML();
443
444         $revision = $page->getCurrentRevision();
445         $transformedContent = $revision->getTransformedContent();
446         $template = new Template('browse', $request,
447                                  array('revision' => $revision,
448                                        'CONTENT' => $transformedContent));
449
450         $data = GeneratePageasXML($template, $pagename);
451
452         if ( !($fd = fopen("$directory/$filename", "wb")) ) {
453             $msg->pushContent(HTML::strong(fmt("couldn't open file '%s' for writing",
454                                                "$directory/$filename")));
455             $request->finish($msg);
456         }
457         $num = fwrite($fd, $data, strlen($data));
458         if($page->getName() != $filename) {
459             $prefix = '';
460             if (isWindows()) {  
461                 // drive where apache is installed
462                 $prefix = '/' . substr($request->get("DOCUMENT_ROOT"),0,2);
463             }
464             $link = LinkURL("file://".$prefix.$directory."/".$filename, 
465                             $filename);
466             $msg->pushContent(HTML::small(_("saved as "), $link, " ... "));
467         }
468         $msg->pushContent(HTML::small(fmt("%s bytes written", $num), "\n"));
469         if (!isa($request,'MockRequest')) {
470             PrintXML($msg);
471             flush();
472         }
473
474         assert($num == strlen($data));
475         fclose($fd);
476     }
477
478     if (!empty($WikiTheme->dumped_images) and is_array($WikiTheme->dumped_images)) {
479         @mkdir("$directory/images");
480         foreach ($WikiTheme->dumped_images as $img_file) {
481             if (($from = $WikiTheme->_findFile($img_file)) and basename($from)) {
482                 $target = "$directory/images/".basename($img_file);
483                 if (copy($WikiTheme->_path . $from, $target)) {
484                     $msg = HTML(HTML::br(), HTML($from), HTML::small(fmt("... copied to %s", $target)));
485                     if (!isa($request,'MockRequest'))
486                         PrintXML($msg);
487                 }
488             } else {
489                 $msg = HTML(HTML::br(), HTML($from), HTML::small(fmt("... not found", $target)));
490                 if (!isa($request,'MockRequest'))
491                     PrintXML($msg);
492             }
493         }
494     }
495     if (!empty($WikiTheme->dumped_buttons) and is_array($WikiTheme->dumped_buttons)) {
496         // Buttons also
497         @mkdir("$directory/images/buttons");
498         foreach ($WikiTheme->dumped_buttons as $text => $img_file) {
499             if (($from = $WikiTheme->_findFile($img_file)) and basename($from)) {
500                 $target = "$directory/images/buttons/".basename($img_file);
501                 if (copy($WikiTheme->_path . $from, $target)) {
502                     $msg = HTML(HTML::br(), HTML($from), HTML::small(fmt("... copied to %s", $target)));
503                     if (!isa($request,'MockRequest'))
504                         PrintXML($msg);
505                 }
506             } else {
507                 $msg = HTML(HTML::br(), HTML($from), HTML::small(fmt("... not found", $target)));
508                 if (!isa($request,'MockRequest'))
509                     PrintXML($msg);
510             }
511         }
512     }
513     if (!empty($WikiTheme->dumped_css) and is_array($WikiTheme->dumped_css)) {
514       foreach ($WikiTheme->dumped_css as $css_file) {
515           if (($from = $WikiTheme->_findFile(basename($css_file))) and basename($from)) {
516               $target = "$directory/" . basename($css_file);
517               if (copy($WikiTheme->_path . $from, $target)) {
518                   $msg = HTML(HTML::br(), HTML($from), HTML::small(fmt("... copied to %s", $target)));
519                   if (!isa($request,'MockRequest'))
520                       PrintXML($msg);
521               }
522           } else {
523               $msg = HTML(HTML::br(), HTML($from), HTML::small(fmt("... not found", $target)));
524               if (!isa($request,'MockRequest'))
525                   PrintXML($msg);
526           }
527       }
528     }
529     $WikiTheme->HTML_DUMP_SUFFIX = '';
530     $WikiTheme->DUMP_MODE = false;
531
532     $request->setArg('pagename',$thispage); // Template::_basepage fix
533     EndLoadDump($request);
534 }
535
536 /* Known problem: any plugins or other code which echo()s text will
537  * lead to a corrupted html zip file which may produce the following
538  * errors upon unzipping:
539  *
540  * warning [wikihtml.zip]:  2401 extra bytes at beginning or within zipfile
541  * file #58:  bad zipfile offset (local header sig):  177561
542  *  (attempting to re-compensate)
543  *
544  * However, the actual wiki page data should be unaffected.
545  */
546 function MakeWikiZipHtml (&$request)
547 {
548     $zipname = "wikihtml.zip";
549     $zip = new ZipWriter("Created by PhpWiki " . PHPWIKI_VERSION, $zipname);
550     $dbi = $request->getDbh();
551     $thispage = $request->getArg('pagename'); // for "Return to ..."
552     if ($exclude = $request->getArg('exclude')) {   // exclude which pagenames
553         $excludeList = explodePageList($exclude); 
554     } else {
555         $excludeList = array();
556     }
557     if ($whichpages = $request->getArg('pages')) {  // which pagenames
558         if ($whichpages == '[]') // current page
559             $whichpages = $thispage;
560         $pages = new WikiDB_Array_PageIterator(explodePageList($whichpages));
561     } else {
562         $pages = $dbi->getAllPages();
563     }
564
565     global $WikiTheme;
566     if (defined('HTML_DUMP_SUFFIX'))
567         $WikiTheme->HTML_DUMP_SUFFIX = HTML_DUMP_SUFFIX;
568
569     /* ignore fatals in plugins */
570     if (check_php_version(4,1)) {
571         global $ErrorManager;
572         $ErrorManager->pushErrorHandler(new WikiFunctionCb('_dump_error_handler'));
573     }
574
575     $request_args = $request->args;
576     
577     while ($page = $pages->next()) {
578         $request->args = $request_args; // some plugins might change them (esp. on POST)
579         if (! $request->getArg('start_debug'))
580             @set_time_limit(30); // Reset watchdog.
581         else    
582             @set_time_limit(240);
583
584         $current = $page->getCurrentRevision();
585         if ($current->getVersion() == 0)
586             continue;
587         $pagename = $page->getName();
588         if (in_array($pagename, $excludeList)) {
589             continue;
590         }
591
592         $attrib = array('mtime'    => $current->get('mtime'),
593                         'is_ascii' => 1);
594         if ($page->get('locked'))
595             $attrib['write_protected'] = 1;
596
597         $request->setArg('pagename',$pagename); // Template::_basepage fix
598         $filename = FilenameForPage($pagename) . $WikiTheme->HTML_DUMP_SUFFIX;
599         $revision = $page->getCurrentRevision();
600
601         $transformedContent = $revision->getTransformedContent();
602
603         $template = new Template('browse', $request,
604                                  array('revision' => $revision,
605                                        'CONTENT' => $transformedContent));
606
607         $data = GeneratePageasXML($template, $pagename);
608
609         $zip->addRegularFile( $filename, $data, $attrib);
610     }
611     // FIXME: Deal with images here.
612     $zip->finish();
613     if (check_php_version(4,1)) {
614         $ErrorManager->popErrorHandler();
615     }
616     $WikiTheme->$HTML_DUMP_SUFFIX = '';
617 }
618
619
620 ////////////////////////////////////////////////////////////////
621 //
622 //  Functions for restoring.
623 //
624 ////////////////////////////////////////////////////////////////
625
626 function SavePage (&$request, &$pageinfo, $source, $filename)
627 {
628     $pagedata    = $pageinfo['pagedata'];    // Page level meta-data.
629     $versiondata = $pageinfo['versiondata']; // Revision level meta-data.
630
631     if (empty($pageinfo['pagename'])) {
632         PrintXML(HTML::dt(HTML::strong(_("Empty pagename!"))));
633         return;
634     }
635
636     if (empty($versiondata['author_id']))
637         $versiondata['author_id'] = $versiondata['author'];
638
639     $pagename = $pageinfo['pagename'];
640     $content  = $pageinfo['content'];
641
642     if ($pagename ==_("InterWikiMap"))
643         $content = _tryinsertInterWikiMap($content);
644
645     $dbi = $request->getDbh();
646     $page = $dbi->getPage($pagename);
647
648     // Try to merge if updated pgsrc contents are different. This
649     // whole thing is hackish
650     //
651     // TODO: try merge unless:
652     // if (current contents = default contents && pgsrc_version >=
653     // pgsrc_version) then just upgrade this pgsrc
654     $needs_merge = false;
655     $merging = false;
656     $overwrite = false;
657
658     if ($request->getArg('merge')) {
659         $merging = true;
660     }
661     else if ($request->getArg('overwrite')) {
662         $overwrite = true;
663     }
664
665     $current = $page->getCurrentRevision();
666     if ( $current and (! $current->hasDefaultContents())
667          && ($current->getPackedContent() != $content)
668          && ($merging == true) ) {
669         include_once('lib/editpage.php');
670         $request->setArg('pagename', $pagename);
671         $r = $current->getVersion();
672         $request->setArg('revision', $current->getVersion());
673         $p = new LoadFileConflictPageEditor($request);
674         $p->_content = $content;
675         $p->_currentVersion = $r - 1;
676         $p->editPage($saveFailed = true);
677         return; //early return
678     }
679
680     foreach ($pagedata as $key => $value) {
681         if (!empty($value))
682             $page->set($key, $value);
683     }
684
685     $mesg = HTML::dd();
686     $skip = false;
687     if ($source)
688         $mesg->pushContent(' ', fmt("from %s", $source));
689
690
691     if (!$current) {
692         //FIXME: This should not happen! (empty vdata, corrupt cache or db)
693         $current = $page->getCurrentRevision();
694     }
695     if ($current->getVersion() == 0) {
696         $mesg->pushContent(' - ', _("new page"));
697         $isnew = true;
698     }
699     else {
700         if ( (! $current->hasDefaultContents())
701              && ($current->getPackedContent() != $content) ) {
702             if ($overwrite) {
703                 $mesg->pushContent(' ',
704                                    fmt("has edit conflicts - overwriting anyway"));
705                 $skip = false;
706                 if (substr_count($source, 'pgsrc')) {
707                     $versiondata['author'] = _("The PhpWiki programming team");
708                     // but leave authorid as userid who loaded the file
709                 }
710             }
711             else {
712                 $mesg->pushContent(' ', fmt("has edit conflicts - skipped"));
713                 $needs_merge = true; // hackish
714                 $skip = true;
715             }
716         }
717         else if ($current->getPackedContent() == $content
718                  && $current->get('author') == $versiondata['author']) {
719             // The page metadata is already changed, we don't need a new revision.
720             // This was called previously "is identical to current version %d - skipped"
721             // which is wrong, since the pagedata was stored, not skipped.
722             $mesg->pushContent(' ',
723                                fmt("content is identical to current version %d - no new revision created",
724                                    $current->getVersion()));
725             $skip = true;
726         }
727         $isnew = false;
728     }
729
730     if (! $skip ) {
731         // in case of failures print the culprit:
732         if (!isa($request,'MockRequest')) {
733             PrintXML(HTML::dt(WikiLink($pagename))); flush();
734         }
735         $new = $page->save($content, WIKIDB_FORCE_CREATE, $versiondata);
736         $dbi->touch();
737         $mesg->pushContent(' ', fmt("- saved to database as version %d",
738                                     $new->getVersion()));
739     }
740     if ($needs_merge) {
741         $f = $source;
742         // hackish, $source contains needed path+filename
743         $f = str_replace(sprintf(_("MIME file %s"), ''), '', $f);
744         $f = str_replace(sprintf(_("Serialized file %s"), ''), '', $f);
745         $f = str_replace(sprintf(_("plain file %s"), ''), '', $f);
746         //check if uploaded file? they pass just the content, but the file is gone
747         if (@stat($f)) {
748             global $WikiTheme;
749             $meb = Button(array('action' => 'loadfile',
750                                 'merge'=> true,
751                                 'source'=> $f),
752                           _("Merge Edit"),
753                           _("PhpWikiAdministration"),
754                           'wikiadmin');
755             $owb = Button(array('action' => 'loadfile',
756                                 'overwrite'=> true,
757                                 'source'=> $f),
758                           _("Restore Anyway"),
759                           _("PhpWikiAdministration"),
760                           'wikiunsafe');
761             $mesg->pushContent(' ', $meb, " ", $owb);
762         } else {
763             $mesg->pushContent(HTML::em(_(" Sorry, cannot merge.")));
764         }
765     }
766
767     if (!isa($request,'MockRequest')) {
768       if ($skip)
769         PrintXML(HTML::dt(HTML::em(WikiLink($pagename))), $mesg);
770       else
771         PrintXML($mesg);
772       flush();
773     }
774 }
775
776 // action=revert (by diff)
777 function RevertPage (&$request)
778 {
779     $mesg = HTML::dd();
780     $pagename = $request->getArg('pagename');
781     $version = $request->getArg('version');
782     if (!$version) {
783         PrintXML(HTML::dt(fmt("Revert")," ",WikiLink($pagename)),
784                  HTML::dd(_("missing required version argument")));
785         return;
786     }
787     $dbi = $request->getDbh();
788     $page = $dbi->getPage($pagename);
789     $current = $page->getCurrentRevision();
790     if ($current->getVersion() == 0) {
791         $mesg->pushContent(' ', _("no page content"));
792         PrintXML(HTML::dt(fmt("Revert")," ",WikiLink($pagename)),
793                  $mesg);
794         return;
795     }
796     if ($current->getVersion() == $version) {
797         $mesg->pushContent(' ', _("same version page"));
798         return;
799     }
800     $rev = $page->getRevision($version);
801     $content = $rev->getPackedContent();
802     $versiondata = $rev->_data;
803     $versiondata['summary'] = sprintf(_("revert to version %d"), $version);
804     $new = $page->save($content, $current->getVersion() + 1, $versiondata);
805     $dbi->touch();
806     $mesg->pushContent(' ', fmt("- version %d saved to database as version %d",
807                                 $version, $new->getVersion()));
808     PrintXML(HTML::dt(fmt("Revert")," ",WikiLink($pagename)),
809              $mesg);
810     flush();
811 }
812
813 function _tryinsertInterWikiMap($content) {
814     $goback = false;
815     if (strpos($content, "<verbatim>")) {
816         //$error_html = " The newly loaded pgsrc already contains a verbatim block.";
817         $goback = true;
818     }
819     if (!$goback && !defined('INTERWIKI_MAP_FILE')) {
820         $error_html = sprintf(" "._("%s: not defined"), "INTERWIKI_MAP_FILE");
821         $goback = true;
822     }
823     $mapfile = FindFile(INTERWIKI_MAP_FILE,1);
824     if (!$goback && !file_exists($mapfile)) {
825         $error_html = sprintf(" "._("%s: file not found"), INTERWIKI_MAP_FILE);
826         $goback = true;
827     }
828
829     if (!empty($error_html))
830         trigger_error(_("Default InterWiki map file not loaded.")
831                       . $error_html, E_USER_NOTICE);
832     if ($goback)
833         return $content;
834
835     // if loading from virgin setup do echo, otherwise trigger_error E_USER_NOTICE
836     if (!isa($GLOBALS['request'],'MockRequest'))
837         echo sprintf(_("Loading InterWikiMap from external file %s."), $mapfile),"<br />";
838
839     $fd = fopen ($mapfile, "rb");
840     $data = fread ($fd, filesize($mapfile));
841     fclose ($fd);
842     $content = $content . "\n<verbatim>\n$data</verbatim>\n";
843     return $content;
844 }
845
846 function ParseSerializedPage($text, $default_pagename, $user)
847 {
848     if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
849         return false;
850
851     $pagehash = unserialize($text);
852
853     // Split up pagehash into four parts:
854     //   pagename
855     //   content
856     //   page-level meta-data
857     //   revision-level meta-data
858
859     if (!defined('FLAG_PAGE_LOCKED'))
860         define('FLAG_PAGE_LOCKED', 1);
861     $pageinfo = array('pagedata'    => array(),
862                       'versiondata' => array());
863
864     $pagedata = &$pageinfo['pagedata'];
865     $versiondata = &$pageinfo['versiondata'];
866
867     // Fill in defaults.
868     if (empty($pagehash['pagename']))
869         $pagehash['pagename'] = $default_pagename;
870     if (empty($pagehash['author'])) {
871         $pagehash['author'] = $user->getId();
872     }
873
874     foreach ($pagehash as $key => $value) {
875         switch($key) {
876             case 'pagename':
877             case 'version':
878             case 'hits':
879                 $pageinfo[$key] = $value;
880                 break;
881             case 'content':
882                 $pageinfo[$key] = join("\n", $value);
883                 break;
884             case 'flags':
885                 if (($value & FLAG_PAGE_LOCKED) != 0)
886                     $pagedata['locked'] = 'yes';
887                 break;
888             case 'owner':
889             case 'created':
890                 $pagedata[$key] = $value;
891                 break;
892             case 'acl':
893             case 'perm':
894                 $pagedata['perm'] = ParseMimeifiedPerm($value);
895                 break;
896             case 'lastmodified':
897                 $versiondata['mtime'] = $value;
898                 break;
899             case 'author':
900             case 'author_id':
901             case 'summary':
902                 $versiondata[$key] = $value;
903                 break;
904         }
905     }
906     return $pageinfo;
907 }
908
909 function SortByPageVersion ($a, $b) {
910     return $a['version'] - $b['version'];
911 }
912
913 function LoadFile (&$request, $filename, $text = false, $mtime = false)
914 {
915     if (!is_string($text)) {
916         // Read the file.
917         $stat  = stat($filename);
918         $mtime = $stat[9];
919         $text  = implode("", file($filename));
920     }
921
922         if (! $request->getArg('start_debug'))
923         @set_time_limit(30); // Reset watchdog.
924     else    
925         @set_time_limit(240);
926
927     // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
928     $basename = basename("/dummy/" . $filename);
929
930     if (!$mtime)
931         $mtime = time();    // Last resort.
932
933     $default_pagename = rawurldecode($basename);
934
935     if ( ($parts = ParseMimeifiedPages($text)) ) {
936         usort($parts, 'SortByPageVersion');
937         foreach ($parts as $pageinfo)
938             SavePage($request, $pageinfo, sprintf(_("MIME file %s"),
939                                                   $filename), $basename);
940     }
941     else if ( ($pageinfo = ParseSerializedPage($text, $default_pagename,
942                                                $request->getUser())) ) {
943         SavePage($request, $pageinfo, sprintf(_("Serialized file %s"),
944                                               $filename), $basename);
945     }
946     else {
947         $user = $request->getUser();
948
949         // Assume plain text file.
950         $pageinfo = array('pagename' => $default_pagename,
951                           'pagedata' => array(),
952                           'versiondata'
953                           => array('author' => $user->getId()),
954                           'content'  => preg_replace('/[ \t\r]*\n/', "\n",
955                                                      chop($text))
956                           );
957         SavePage($request, $pageinfo, sprintf(_("plain file %s"), $filename),
958                  $basename);
959     }
960 }
961
962 function LoadZip (&$request, $zipfile, $files = false, $exclude = false) {
963     $zip = new ZipReader($zipfile);
964     while (list ($fn, $data, $attrib) = $zip->readFile()) {
965         // FIXME: basename("filewithnoslashes") seems to return
966         // garbage sometimes.
967         $fn = basename("/dummy/" . $fn);
968         if ( ($files && !in_array($fn, $files))
969              || ($exclude && in_array($fn, $exclude)) ) {
970             PrintXML(HTML::dt(WikiLink($fn)),
971                      HTML::dd(_("Skipping")));
972             flush();
973             continue;
974         }
975
976         LoadFile($request, $fn, $data, $attrib['mtime']);
977     }
978 }
979
980 function LoadDir (&$request, $dirname, $files = false, $exclude = false) {
981     $fileset = new LimitedFileSet($dirname, $files, $exclude);
982
983     if (!$files and ($skiplist = $fileset->getSkippedFiles())) {
984         PrintXML(HTML::dt(HTML::strong(_("Skipping"))));
985         $list = HTML::ul();
986         foreach ($skiplist as $file)
987             $list->pushContent(HTML::li(WikiLink($file)));
988         PrintXML(HTML::dd($list));
989     }
990
991     // Defer HomePage loading until the end. If anything goes wrong
992     // the pages can still be loaded again.
993     $files = $fileset->getFiles();
994     if (in_array(HOME_PAGE, $files)) {
995         $files = array_diff($files, array(HOME_PAGE));
996         $files[] = HOME_PAGE;
997     }
998     foreach ($files as $file) {
999         if (substr($file,-1,1) != '~') // refuse to load backup files
1000             LoadFile($request, "$dirname/$file");
1001     }
1002 }
1003
1004 class LimitedFileSet extends FileSet {
1005     function LimitedFileSet($dirname, $_include, $exclude) {
1006         $this->_includefiles = $_include;
1007         $this->_exclude = $exclude;
1008         $this->_skiplist = array();
1009         parent::FileSet($dirname);
1010     }
1011
1012     function _filenameSelector($fn) {
1013         $incl = &$this->_includefiles;
1014         $excl = &$this->_exclude;
1015
1016         if ( ($incl && !in_array($fn, $incl))
1017              || ($excl && in_array($fn, $excl)) ) {
1018             $this->_skiplist[] = $fn;
1019             return false;
1020         } else {
1021             return true;
1022         }
1023     }
1024
1025     function getSkippedFiles () {
1026         return $this->_skiplist;
1027     }
1028 }
1029
1030
1031 function IsZipFile ($filename_or_fd)
1032 {
1033     // See if it looks like zip file
1034     if (is_string($filename_or_fd))
1035     {
1036         $fd    = fopen($filename_or_fd, "rb");
1037         $magic = fread($fd, 4);
1038         fclose($fd);
1039     }
1040     else
1041     {
1042         $fpos  = ftell($filename_or_fd);
1043         $magic = fread($filename_or_fd, 4);
1044         fseek($filename_or_fd, $fpos);
1045     }
1046
1047     return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
1048 }
1049
1050
1051 function LoadAny (&$request, $file_or_dir, $files = false, $exclude = false)
1052 {
1053     // Try urlencoded filename for accented characters.
1054     if (!file_exists($file_or_dir)) {
1055         // Make sure there are slashes first to avoid confusing phps
1056         // with broken dirname or basename functions.
1057         // FIXME: windows uses \ and :
1058         if (is_integer(strpos($file_or_dir, "/"))) {
1059             $file_or_dir = FindFile($file_or_dir);
1060             // Panic
1061             if (!file_exists($file_or_dir))
1062                 $file_or_dir = dirname($file_or_dir) . "/"
1063                     . urlencode(basename($file_or_dir));
1064         } else {
1065             // This is probably just a file.
1066             $file_or_dir = urlencode($file_or_dir);
1067         }
1068     }
1069
1070     $type = filetype($file_or_dir);
1071     if ($type == 'link') {
1072         // For symbolic links, use stat() to determine
1073         // the type of the underlying file.
1074         list(,,$mode) = stat($file_or_dir);
1075         $type = ($mode >> 12) & 017;
1076         if ($type == 010)
1077             $type = 'file';
1078         elseif ($type == 004)
1079             $type = 'dir';
1080     }
1081
1082     if (! $type) {
1083         $request->finish(fmt("Unable to load: %s", $file_or_dir));
1084     }
1085     else if ($type == 'dir') {
1086         LoadDir($request, $file_or_dir, $files, $exclude);
1087     }
1088     else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
1089     {
1090         $request->finish(fmt("Bad file type: %s", $type));
1091     }
1092     else if (IsZipFile($file_or_dir)) {
1093         LoadZip($request, $file_or_dir, $files, $exclude);
1094     }
1095     else /* if (!$files || in_array(basename($file_or_dir), $files)) */
1096     {
1097         LoadFile($request, $file_or_dir);
1098     }
1099 }
1100
1101 function LoadFileOrDir (&$request)
1102 {
1103     $source = $request->getArg('source');
1104     $finder = new FileFinder;
1105     $source = $finder->slashifyPath($source);
1106     $page = rawurldecode(basename($source));
1107     StartLoadDump($request, fmt("Loading '%s'", 
1108         HTML(dirname($source),
1109              dirname($source) ? "/" : "",
1110              WikiLink($page,'auto'))));
1111     echo "<dl>\n";
1112     LoadAny($request, $source);
1113     echo "</dl>\n";
1114     EndLoadDump($request);
1115 }
1116
1117 function SetupWiki (&$request)
1118 {
1119     global $GenericPages, $LANG;
1120
1121
1122     //FIXME: This is a hack (err, "interim solution")
1123     // This is a bogo-bogo-login:  Login without
1124     // saving login information in session state.
1125     // This avoids logging in the unsuspecting
1126     // visitor as "The PhpWiki programming team".
1127     //
1128     // This really needs to be cleaned up...
1129     // (I'm working on it.)
1130     $real_user = $request->_user;
1131     if (ENABLE_USER_NEW)
1132         $request->_user = new _BogoUser(_("The PhpWiki programming team"));
1133
1134     else
1135         $request->_user = new WikiUser($request, _("The PhpWiki programming team"),
1136                                        WIKIAUTH_BOGO);
1137
1138     StartLoadDump($request, _("Loading up virgin wiki"));
1139     echo "<dl>\n";
1140
1141     $pgsrc = FindLocalizedFile(WIKI_PGSRC);
1142     $default_pgsrc = FindFile(DEFAULT_WIKI_PGSRC);
1143
1144     $request->setArg('overwrite',true);
1145     if ($default_pgsrc != $pgsrc) {
1146         LoadAny($request, $default_pgsrc, $GenericPages);
1147     }
1148     $request->setArg('overwrite',false);
1149     LoadAny($request, $pgsrc);
1150
1151     // Ensure that all mandatory pages are loaded
1152     $finder = new FileFinder;
1153     foreach (array_merge(explode(':','OldTextFormattingRules:TextFormattingRules:PhpWikiAdministration'),
1154                          $GLOBALS['AllActionPages'],
1155                          array(constant('HOME_PAGE'))) as $f) {
1156         $page = gettext($f);
1157         if (isSubPage($page))
1158             $page = urlencode($page);
1159         if (! $request->_dbi->isWikiPage(urldecode($page)) ) {
1160             // translated version provided?
1161             if ($lf = FindLocalizedFile($pgsrc . $finder->_pathsep . $page, 1))
1162                 LoadAny($request, $lf);
1163             else { // load english version of required action page
1164                 LoadAny($request, FindFile(DEFAULT_WIKI_PGSRC . $finder->_pathsep . urlencode($f)));
1165                 $page = $f;
1166             }
1167         }
1168         if (!$request->_dbi->isWikiPage(urldecode($page))) {
1169             trigger_error(sprintf("Mandatory file %s couldn't be loaded!", $page),
1170                           E_USER_WARNING);
1171         }
1172     }
1173
1174     echo "</dl>\n";
1175     EndLoadDump($request);
1176 }
1177
1178 function LoadPostFile (&$request)
1179 {
1180     $upload = $request->getUploadedFile('file');
1181
1182     if (!$upload)
1183         $request->finish(_("No uploaded file to upload?")); // FIXME: more concise message
1184
1185
1186     // Dump http headers.
1187     StartLoadDump($request, sprintf(_("Uploading %s"), $upload->getName()));
1188     echo "<dl>\n";
1189
1190     $fd = $upload->open();
1191     if (IsZipFile($fd))
1192         LoadZip($request, $fd, false, array(_("RecentChanges")));
1193     else
1194         LoadFile($request, $upload->getName(), $upload->getContents());
1195
1196     echo "</dl>\n";
1197     EndLoadDump($request);
1198 }
1199
1200 /**
1201  $Log: not supported by cvs2svn $
1202  Revision 1.123  2004/09/25 16:26:54  rurban
1203  deferr notifies (to be improved)
1204
1205  Revision 1.122  2004/09/17 14:25:45  rurban
1206  update comments
1207
1208  Revision 1.121  2004/09/08 13:38:00  rurban
1209  improve loadfile stability by using markup=2 as default for undefined markup-style.
1210  use more refs for huge objects.
1211  fix debug=static issue in WikiPluginCached
1212
1213  Revision 1.120  2004/07/08 19:04:42  rurban
1214  more unittest fixes (file backend, metadata RatingsDb)
1215
1216  Revision 1.119  2004/07/08 15:23:59  rurban
1217  less verbose for tests
1218
1219  Revision 1.118  2004/07/08 13:50:32  rurban
1220  various unit test fixes: print error backtrace on _DEBUG_TRACE; allusers fix; new PHPWIKI_NOMAIN constant for omitting the mainloop
1221
1222  Revision 1.117  2004/07/02 09:55:58  rurban
1223  more stability fixes: new DISABLE_GETIMAGESIZE if your php crashes when loading LinkIcons: failing getimagesize in old phps; blockparser stabilized
1224
1225  Revision 1.116  2004/07/01 09:05:41  rurban
1226  support pages and exclude arguments for all 4 dump methods
1227
1228  Revision 1.115  2004/07/01 08:51:22  rurban
1229  dumphtml: added exclude, print pagename before processing
1230
1231  Revision 1.114  2004/06/28 12:51:41  rurban
1232  improved dumphtml and virgin setup
1233
1234  Revision 1.113  2004/06/27 10:26:02  rurban
1235  oci8 patch by Philippe Vanhaesendonck + some ADODB notes+fixes
1236
1237  Revision 1.112  2004/06/25 14:29:20  rurban
1238  WikiGroup refactoring:
1239    global group attached to user, code for not_current user.
1240    improved helpers for special groups (avoid double invocations)
1241  new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
1242  fixed a XHTML validation error on userprefs.tmpl
1243
1244  Revision 1.111  2004/06/21 16:38:55  rurban
1245  fixed the StartLoadDump html argument hack.
1246
1247  Revision 1.110  2004/06/21 16:22:30  rurban
1248  add DEFAULT_DUMP_DIR and HTML_DUMP_DIR constants, for easier cmdline dumps,
1249  fixed dumping buttons locally (images/buttons/),
1250  support pages arg for dumphtml,
1251  optional directory arg for dumpserial + dumphtml,
1252  fix a AllPages warning,
1253  show dump warnings/errors on DEBUG,
1254  don't warn just ignore on wikilens pagelist columns, if not loaded.
1255  RateIt pagelist column is called "rating", not "ratingwidget" (Dan?)
1256
1257  Revision 1.109  2004/06/17 11:31:05  rurban
1258  jump back to label after dump/upgrade
1259
1260  Revision 1.108  2004/06/16 12:43:01  rurban
1261  4.0.6 cannot use this errorhandler (not found)
1262
1263  Revision 1.107  2004/06/14 11:31:37  rurban
1264  renamed global $Theme to $WikiTheme (gforge nameclash)
1265  inherit PageList default options from PageList
1266    default sortby=pagename
1267  use options in PageList_Selectable (limit, sortby, ...)
1268  added action revert, with button at action=diff
1269  added option regex to WikiAdminSearchReplace
1270
1271  Revision 1.106  2004/06/13 13:54:25  rurban
1272  Catch fatals on the four dump calls (as file and zip, as html and mimified)
1273  FoafViewer: Check against external requirements, instead of fatal.
1274  Change output for xhtmldumps: using file:// urls to the local fs.
1275  Catch SOAP fatal by checking for GOOGLE_LICENSE_KEY
1276  Import GOOGLE_LICENSE_KEY and FORTUNE_DIR from config.ini.
1277
1278  Revision 1.105  2004/06/08 19:48:16  rurban
1279  fixed foreign setup: no ugly skipped msg for the GenericPages, load english actionpages if translated not found
1280
1281  Revision 1.104  2004/06/08 13:51:57  rurban
1282  some comments only
1283
1284  Revision 1.103  2004/06/08 10:54:46  rurban
1285  better acl dump representation, read back acl and owner
1286
1287  Revision 1.102  2004/06/06 16:58:51  rurban
1288  added more required ActionPages for foreign languages
1289  install now english ActionPages if no localized are found. (again)
1290  fixed default anon user level to be 0, instead of -1
1291    (wrong "required administrator to view this page"...)
1292
1293  Revision 1.101  2004/06/04 20:32:53  rurban
1294  Several locale related improvements suggested by Pierrick Meignen
1295  LDAP fix by John Cole
1296  reanable admin check without ENABLE_PAGEPERM in the admin plugins
1297
1298  Revision 1.100  2004/05/02 21:26:38  rurban
1299  limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
1300    because they will not survive db sessions, if too large.
1301  extended action=upgrade
1302  some WikiTranslation button work
1303  revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
1304  some temp. session debug statements
1305
1306  Revision 1.99  2004/05/02 15:10:07  rurban
1307  new finally reliable way to detect if /index.php is called directly
1308    and if to include lib/main.php
1309  new global AllActionPages
1310  SetupWiki now loads all mandatory pages: HOME_PAGE, action pages, and warns if not.
1311  WikiTranslation what=buttons for Carsten to create the missing MacOSX buttons
1312  PageGroupTestOne => subpages
1313  renamed PhpWikiRss to PhpWikiRecentChanges
1314  more docs, default configs, ...
1315
1316  Revision 1.98  2004/04/29 23:25:12  rurban
1317  re-ordered locale init (as in 1.3.9)
1318  fixed loadfile with subpages, and merge/restore anyway
1319    (sf.net bug #844188)
1320
1321  Revision 1.96  2004/04/19 23:13:03  zorloc
1322  Connect the rest of PhpWiki to the IniConfig system.  Also the keyword regular expression is not a config setting
1323
1324  Revision 1.95  2004/04/18 01:11:52  rurban
1325  more numeric pagename fixes.
1326  fixed action=upload with merge conflict warnings.
1327  charset changed from constant to global (dynamic utf-8 switching)
1328
1329  Revision 1.94  2004/03/14 16:36:37  rurban
1330  dont load backup files
1331
1332  Revision 1.93  2004/02/26 03:22:05  rurban
1333  also copy css and images with XHTML Dump
1334
1335  Revision 1.92  2004/02/26 02:25:54  rurban
1336  fix empty and #-anchored links in XHTML Dumps
1337
1338  Revision 1.91  2004/02/24 17:19:37  rurban
1339  debugging helpers only
1340
1341  Revision 1.90  2004/02/24 17:09:24  rurban
1342  fixed \r\r\n with dumping on windows
1343
1344  Revision 1.88  2004/02/22 23:20:31  rurban
1345  fixed DumpHtmlToDir,
1346  enhanced sortby handling in PageList
1347    new button_heading th style (enabled),
1348  added sortby and limit support to the db backends and plugins
1349    for paging support (<<prev, next>> links on long lists)
1350
1351  Revision 1.87  2004/01/26 09:17:49  rurban
1352  * changed stored pref representation as before.
1353    the array of objects is 1) bigger and 2)
1354    less portable. If we would import packed pref
1355    objects and the object definition was changed, PHP would fail.
1356    This doesn't happen with an simple array of non-default values.
1357  * use $prefs->retrieve and $prefs->store methods, where retrieve
1358    understands the interim format of array of objects also.
1359  * simplified $prefs->get() and fixed $prefs->set()
1360  * added $user->_userid and class '_WikiUser' portability functions
1361  * fixed $user object ->_level upgrading, mostly using sessions.
1362    this fixes yesterdays problems with loosing authorization level.
1363  * fixed WikiUserNew::checkPass to return the _level
1364  * fixed WikiUserNew::isSignedIn
1365  * added explodePageList to class PageList, support sortby arg
1366  * fixed UserPreferences for WikiUserNew
1367  * fixed WikiPlugin for empty defaults array
1368  * UnfoldSubpages: added pagename arg, renamed pages arg,
1369    removed sort arg, support sortby arg
1370
1371  Revision 1.86  2003/12/02 16:18:26  carstenklapp
1372  Minor enhancement: Provide more meaningful filenames for WikiDB zip
1373  dumps & snapshots.
1374
1375  Revision 1.85  2003/11/30 18:18:13  carstenklapp
1376  Minor code optimization: use include_once instead of require_once
1377  inside functions that might not always called.
1378
1379  Revision 1.84  2003/11/26 20:47:47  carstenklapp
1380  Redo bugfix: My last refactoring broke merge-edit & overwrite
1381  functionality again, should be fixed now. Sorry.
1382
1383  Revision 1.83  2003/11/20 22:18:54  carstenklapp
1384  New feature: h1 during merge-edit displays WikiLink to original page.
1385  Internal changes: Replaced some hackish url-generation code in
1386  function SavePage (for pgsrc merge-edit) with appropriate Button()
1387  calls.
1388
1389  Revision 1.82  2003/11/18 19:48:01  carstenklapp
1390  Fixed missing gettext _() for button name.
1391
1392  Revision 1.81  2003/11/18 18:28:35  carstenklapp
1393  Bugfix: In the Load File function of PhpWikiAdministration: When doing
1394  a "Merge Edit" or "Restore Anyway", page names containing accented
1395  letters (such as locale/de/pgsrc/G%E4steBuch) would produce a file not
1396  found error (Use FilenameForPage funtion to urlencode page names).
1397
1398  Revision 1.80  2003/03/07 02:46:57  dairiki
1399  Omit checks for safe_mode before set_time_limit().  Just prefix the
1400  set_time_limit() calls with @ so that they fail silently if not
1401  supported.
1402
1403  Revision 1.79  2003/02/26 01:56:05  dairiki
1404  Only zip pages with legal pagenames.
1405
1406  Revision 1.78  2003/02/24 02:05:43  dairiki
1407  Fix "n bytes written" message when dumping HTML.
1408
1409  Revision 1.77  2003/02/21 04:12:05  dairiki
1410  Minor fixes for new cached markup.
1411
1412  Revision 1.76  2003/02/16 19:47:17  dairiki
1413  Update WikiDB timestamp when editing or deleting pages.
1414
1415  Revision 1.75  2003/02/15 03:04:30  dairiki
1416  Fix for WikiUser constructor API change.
1417
1418  Revision 1.74  2003/02/15 02:18:04  dairiki
1419  When default language was English (at least), pgsrc was being
1420  loaded twice.
1421
1422  LimitedFileSet: Fix typo/bug. ($include was being ignored.)
1423
1424  SetupWiki(): Fix bugs in loading of $GenericPages.
1425
1426  Revision 1.73  2003/01/28 21:09:17  zorloc
1427  The get_cfg_var() function should only be used when one is
1428  interested in the value from php.ini or similar. Use ini_get()
1429  instead to get the effective value of a configuration variable.
1430  -- Martin Geisler
1431
1432  Revision 1.72  2003/01/03 22:25:53  carstenklapp
1433  Cosmetic fix to "Merge Edit" & "Overwrite" buttons. Added "The PhpWiki
1434  programming team" as author when loading from pgsrc. Source
1435  reformatting.
1436
1437  Revision 1.71  2003/01/03 02:48:05  carstenklapp
1438  function SavePage: Added loadfile options for overwriting or merge &
1439  compare a loaded pgsrc file with an existing page.
1440
1441  function LoadAny: Added a general error message when unable to load a
1442  file instead of defaulting to "Bad file type".
1443
1444  */
1445
1446 // For emacs users
1447 // Local Variables:
1448 // mode: php
1449 // tab-width: 8
1450 // c-basic-offset: 4
1451 // c-hanging-comment-ender-p: nil
1452 // indent-tabs-mode: nil
1453 // End:
1454 ?>