2 rcs_id('$Id: loadsave.php,v 1.91 2004-02-24 17:19:37 rurban Exp $');
5 Copyright 1999, 2000, 2001, 2002 $ThePhpWikiProgrammingTeam
7 This file is part of PhpWiki.
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.
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.
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
25 require_once("lib/ziplib.php");
26 require_once("lib/Template.php");
28 function StartLoadDump(&$request, $title, $html = '')
30 // FIXME: This is a hack
31 $tmpl = Template('html', array('TITLE' => $title,
33 'CONTENT' => '%BODY%'));
34 echo ereg_replace('%BODY%.*', '', $tmpl->getExpansion($html));
37 function EndLoadDump(&$request)
39 // FIXME: This is a hack
40 $pagelink = WikiLink($request->getPage());
42 PrintXML(HTML::p(HTML::strong(_("Complete."))),
43 HTML::p(fmt("Return to %s", $pagelink)));
44 echo "</body></html>\n";
48 ////////////////////////////////////////////////////////////////
50 // Functions for dumping.
52 ////////////////////////////////////////////////////////////////
56 * http://www.nacs.uci.edu/indiv/ehood/MIME/2045/rfc2045.html
57 * http://www.faqs.org/rfcs/rfc2045.html
58 * (RFC 1521 has been superceeded by RFC 2045 & others).
60 * Also see http://www.faqs.org/rfcs/rfc2822.html
62 function MailifyPage ($page, $nversions = 1)
64 $current = $page->getCurrentRevision();
67 if (STRICT_MAILABLE_PAGEDUMPS) {
68 $from = defined('SERVER_ADMIN') ? SERVER_ADMIN : 'foo@bar';
69 //This is for unix mailbox format: (not RFC (2)822)
70 // $head .= "From $from " . CTime(time()) . "\r\n";
71 $head .= "Subject: " . rawurlencode($page->getName()) . "\r\n";
72 $head .= "From: $from (PhpWiki)\r\n";
73 // RFC 2822 requires only a Date: and originator (From:)
74 // field, however the obsolete standard RFC 822 also
75 // requires a destination field.
76 $head .= "To: $from (PhpWiki)\r\n";
78 $head .= "Date: " . Rfc2822DateTime($current->get('mtime')) . "\r\n";
79 $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n",
82 // This should just be entered by hand (or by script?)
83 // in the actual pgsrc files, since only they should have
85 //$head .= "X-Rcs-Id: \$Id\$\r\n";
87 $iter = $page->getAllRevisions();
89 while ($revision = $iter->next()) {
90 $parts[] = MimeifyPageRevision($revision);
91 if ($nversions > 0 && count($parts) >= $nversions)
94 if (count($parts) > 1)
95 return $head . MimeMultipart($parts);
97 return $head . $parts[0];
101 * Compute filename to used for storing contents of a wiki page.
103 * Basically we do a rawurlencode() which encodes everything except
104 * ASCII alphanumerics and '.', '-', and '_'.
106 * But we also want to encode leading dots to avoid filenames like
107 * '.', and '..'. (Also, there's no point in generating "hidden" file
108 * names, like '.foo'.)
110 * @param $pagename string Pagename.
111 * @return string Filename for page.
113 function FilenameForPage ($pagename)
115 $enc = rawurlencode($pagename);
116 return preg_replace('/^\./', '%2e', $enc);
120 * The main() function which generates a zip archive of a PhpWiki.
122 * If $include_archive is false, only the current version of each page
123 * is included in the zip file; otherwise all archived versions are
126 function MakeWikiZip (&$request)
128 if ($request->getArg('include') == 'all') {
129 $zipname = WIKI_NAME . _("FullDump") . date('Ymd-Hi') . '.zip';
130 $include_archive = true;
133 $zipname = WIKI_NAME . _("LatestSnapshot") . date('Ymd-Hi') . '.zip';
134 $include_archive = false;
139 $zip = new ZipWriter("Created by PhpWiki " . PHPWIKI_VERSION, $zipname);
141 $dbi = $request->getDbh();
142 $pages = $dbi->getAllPages();
143 while ($page = $pages->next()) {
144 if (! $request->getArg('start_debug'))
145 @set_time_limit(30); // Reset watchdog
147 $current = $page->getCurrentRevision();
148 if ($current->getVersion() == 0)
151 $wpn = new WikiPageName($page->getName());
152 if (!$wpn->isValid())
155 $attrib = array('mtime' => $current->get('mtime'),
157 if ($page->get('locked'))
158 $attrib['write_protected'] = 1;
160 if ($include_archive)
161 $content = MailifyPage($page, 0);
163 $content = MailifyPage($page);
165 $zip->addRegularFile( FilenameForPage($page->getName()),
171 function DumpToDir (&$request)
173 $directory = $request->getArg('directory');
174 if (empty($directory))
175 $request->finish(_("You must specify a directory to dump to"));
177 // see if we can access the directory the user wants us to use
178 if (! file_exists($directory)) {
179 if (! mkdir($directory, 0755))
180 $request->finish(fmt("Cannot create directory '%s'", $directory));
182 $html = HTML::p(fmt("Created directory '%s' for the page dump...",
185 $html = HTML::p(fmt("Using directory '%s'", $directory));
188 StartLoadDump($request, _("Dumping Pages"), $html);
190 $dbi = $request->getDbh();
191 $pages = $dbi->getAllPages();
193 while ($page = $pages->next()) {
194 if (! $request->getArg('start_debug'))
195 @set_time_limit(30); // Reset watchdog.
197 $filename = FilenameForPage($page->getName());
199 $msg = HTML(HTML::br(), $page->getName(), ' ... ');
201 if($page->getName() != $filename) {
202 $msg->pushContent(HTML::small(fmt("saved as %s", $filename)),
206 if ($request->getArg('include') == 'all')
207 $data = MailifyPage($page, 0);
209 $data = MailifyPage($page);
211 if ( !($fd = fopen("$directory/$filename", "wb")) ) {
212 $msg->pushContent(HTML::strong(fmt("couldn't open file '%s' for writing",
213 "$directory/$filename")));
214 $request->finish($msg);
217 $num = fwrite($fd, $data, strlen($data));
218 $msg->pushContent(HTML::small(fmt("%s bytes written", $num)));
222 assert($num == strlen($data));
226 EndLoadDump($request);
230 function DumpHtmlToDir (&$request)
232 $directory = $request->getArg('directory');
233 if (empty($directory))
234 $request->finish(_("You must specify a directory to dump to"));
236 // see if we can access the directory the user wants us to use
237 if (! file_exists($directory)) {
238 if (! mkdir($directory, 0755))
239 $request->finish(fmt("Cannot create directory '%s'", $directory));
241 $html = HTML::p(fmt("Created directory '%s' for the page dump...",
244 $html = HTML::p(fmt("Using directory '%s'", $directory));
247 StartLoadDump($request, _("Dumping Pages"), $html);
248 $thispage = $request->getArg('pagename'); // for "Return to ..."
250 $dbi = $request->getDbh();
251 $pages = $dbi->getAllPages();
253 global $HTML_DUMP_SUFFIX, $Theme;
254 if ($HTML_DUMP_SUFFIX)
255 $Theme->HTML_DUMP_SUFFIX = $HTML_DUMP_SUFFIX;
257 while ($page = $pages->next()) {
258 if (! $request->getArg('start_debug'))
259 @set_time_limit(30); // Reset watchdog.
261 $pagename = $page->getName();
262 $request->setArg('pagename',$pagename); // Template::_basepage fix
263 $filename = FilenameForPage($pagename) . $Theme->HTML_DUMP_SUFFIX;
265 $msg = HTML(HTML::br(), $pagename, ' ... ');
267 if($page->getName() != $filename) {
268 $msg->pushContent(HTML::small(fmt("saved as %s", $filename)),
272 $revision = $page->getCurrentRevision();
273 $transformedContent = $revision->getTransformedContent();
274 $template = new Template('browse', $request,
275 array('revision' => $revision,
276 'CONTENT' => $transformedContent));
278 $data = GeneratePageasXML($template, $pagename);
280 if ( !($fd = fopen("$directory/$filename", "wb")) ) {
281 $msg->pushContent(HTML::strong(fmt("couldn't open file '%s' for writing",
282 "$directory/$filename")));
283 $request->finish($msg);
286 $num = fwrite($fd, $data, strlen($data));
287 $msg->pushContent(HTML::small(fmt("%s bytes written", $num), "\n"));
291 assert($num == strlen($data));
295 //CopyImageFiles() will go here;
296 $Theme->$HTML_DUMP_SUFFIX = '';
298 $request->setArg('pagename',$thispage); // Template::_basepage fix
299 EndLoadDump($request);
302 /* Known problem: any plugins or other code which echo()s text will
303 * lead to a corrupted html zip file which may produce the following
304 * errors upon unzipping:
306 * warning [wikihtml.zip]: 2401 extra bytes at beginning or within zipfile
307 * file #58: bad zipfile offset (local header sig): 177561
308 * (attempting to re-compensate)
310 * However, the actual wiki page data should be unaffected.
312 function MakeWikiZipHtml (&$request)
314 $zipname = "wikihtml.zip";
315 $zip = new ZipWriter("Created by PhpWiki " . PHPWIKI_VERSION, $zipname);
316 $dbi = $request->getDbh();
317 $pages = $dbi->getAllPages();
319 global $HTML_DUMP_SUFFIX, $Theme;
320 if ($HTML_DUMP_SUFFIX)
321 $Theme->HTML_DUMP_SUFFIX = $HTML_DUMP_SUFFIX;
323 while ($page = $pages->next()) {
324 if (! $request->getArg('start_debug'))
325 @set_time_limit(30); // Reset watchdog.
327 $current = $page->getCurrentRevision();
328 if ($current->getVersion() == 0)
331 $attrib = array('mtime' => $current->get('mtime'),
333 if ($page->get('locked'))
334 $attrib['write_protected'] = 1;
336 $pagename = $page->getName();
337 $request->setArg('pagename',$pagename); // Template::_basepage fix
338 $filename = FilenameForPage($pagename) . $Theme->HTML_DUMP_SUFFIX;
339 $revision = $page->getCurrentRevision();
341 $transformedContent = $revision->getTransformedContent();
343 $template = new Template('browse', $request,
344 array('revision' => $revision,
345 'CONTENT' => $transformedContent));
347 $data = GeneratePageasXML($template, $pagename);
349 $zip->addRegularFile( $filename, $data, $attrib);
351 // FIXME: Deal with images here.
353 $Theme->$HTML_DUMP_SUFFIX = '';
357 ////////////////////////////////////////////////////////////////
359 // Functions for restoring.
361 ////////////////////////////////////////////////////////////////
363 function SavePage (&$request, $pageinfo, $source, $filename)
365 $pagedata = $pageinfo['pagedata']; // Page level meta-data.
366 $versiondata = $pageinfo['versiondata']; // Revision level meta-data.
368 if (empty($pageinfo['pagename'])) {
369 PrintXML(HTML::dt(HTML::strong(_("Empty pagename!"))));
373 if (empty($versiondata['author_id']))
374 $versiondata['author_id'] = $versiondata['author'];
376 $pagename = $pageinfo['pagename'];
377 $content = $pageinfo['content'];
379 if ($pagename ==_("InterWikiMap"))
380 $content = _tryinsertInterWikiMap($content);
382 $dbi = $request->getDbh();
383 $page = $dbi->getPage($pagename);
385 $current = $page->getCurrentRevision();
386 // Try to merge if updated pgsrc contents are different. This
387 // whole thing is hackish
389 // TODO: try merge unless:
390 // if (current contents = default contents && pgsrc_version >=
391 // pgsrc_version) then just upgrade this pgsrc
392 $needs_merge = false;
396 if ($request->getArg('merge')) {
399 else if ($request->getArg('overwrite')) {
403 if ( (! $current->hasDefaultContents())
404 && ($current->getPackedContent() != $content)
405 && ($merging == true) ) {
406 include_once('lib/editpage.php');
407 $request->setArg('pagename', $pagename);
408 $r = $current->getVersion();
409 $request->setArg('revision', $current->getVersion());
410 $p = new LoadFileConflictPageEditor($request);
411 $p->_content = $content;
412 $p->_currentVersion = $r - 1;
413 $p->editPage($saveFailed = true);
414 return; //early return
417 foreach ($pagedata as $key => $value) {
419 $page->set($key, $value);
425 $mesg->pushContent(' ', fmt("from %s", $source));
428 $current = $page->getCurrentRevision();
429 if ($current->getVersion() == 0) {
430 $mesg->pushContent(' ', _("new page"));
434 if ( (! $current->hasDefaultContents())
435 && ($current->getPackedContent() != $content) ) {
437 $mesg->pushContent(' ',
438 fmt("has edit conflicts - overwriting anyway"));
440 if (substr_count($source, 'pgsrc')) {
441 $versiondata['author'] = _("The PhpWiki programming team");
442 // but leave authorid as userid who loaded the file
446 $mesg->pushContent(' ', fmt("has edit conflicts - skipped"));
447 $needs_merge = true; // hackish
451 else if ($current->getPackedContent() == $content
452 && $current->get('author') == $versiondata['author']) {
453 $mesg->pushContent(' ',
454 fmt("is identical to current version %d - skipped",
455 $current->getVersion()));
462 $new = $page->save($content, WIKIDB_FORCE_CREATE, $versiondata);
464 $mesg->pushContent(' ', fmt("- saved to database as version %d",
465 $new->getVersion()));
469 // hackish, $source contains needed path+filename
470 $f = str_replace(sprintf(_("MIME file %s"), ''), '', $f);
471 $f = str_replace(sprintf(_("Serialized file %s"), ''), '', $f);
472 $f = str_replace(sprintf(_("plain file %s"), ''), '', $f);
473 //check if uploaded file? they pass just the content, but the file is gone
476 $meb = Button(array('action' => 'loadfile',
480 _("PhpWikiAdministration"),
482 $owb = Button(array('action' => 'loadfile',
486 _("PhpWikiAdministration"),
489 $mesg->pushContent(' ', $meb, " ", $owb);
493 PrintXML(HTML::dt(HTML::em(WikiLink($pagename))), $mesg);
495 PrintXML(HTML::dt(WikiLink($pagename)), $mesg);
499 function _tryinsertInterWikiMap($content) {
501 if (strpos($content, "<verbatim>")) {
502 //$error_html = " The newly loaded pgsrc already contains a verbatim block.";
505 if (!$goback && !defined('INTERWIKI_MAP_FILE')) {
506 $error_html = sprintf(" "._("%s: not defined"), "INTERWIKI_MAP_FILE");
509 if (!$goback && !file_exists(INTERWIKI_MAP_FILE)) {
510 $error_html = sprintf(" "._("%s: file not found"), INTERWIKI_MAP_FILE);
514 if (!empty($error_html))
515 trigger_error(_("Default InterWiki map file not loaded.")
516 . $error_html, E_USER_NOTICE);
521 $filename = INTERWIKI_MAP_FILE;
522 trigger_error(sprintf(_("Loading InterWikiMap from external file %s."),
523 $filename), E_USER_NOTICE);
525 $fd = fopen ($filename, "rb");
526 $data = fread ($fd, filesize($filename));
528 $content = $content . "\n<verbatim>\n$data</verbatim>\n";
532 function ParseSerializedPage($text, $default_pagename, $user)
534 if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
537 $pagehash = unserialize($text);
539 // Split up pagehash into four parts:
542 // page-level meta-data
543 // revision-level meta-data
545 if (!defined('FLAG_PAGE_LOCKED'))
546 define('FLAG_PAGE_LOCKED', 1);
547 $pageinfo = array('pagedata' => array(),
548 'versiondata' => array());
550 $pagedata = &$pageinfo['pagedata'];
551 $versiondata = &$pageinfo['versiondata'];
554 if (empty($pagehash['pagename']))
555 $pagehash['pagename'] = $default_pagename;
556 if (empty($pagehash['author'])) {
557 $pagehash['author'] = $user->getId();
560 foreach ($pagehash as $key => $value) {
565 $pageinfo[$key] = $value;
568 $pageinfo[$key] = join("\n", $value);
571 if (($value & FLAG_PAGE_LOCKED) != 0)
572 $pagedata['locked'] = 'yes';
575 $pagedata[$key] = $value;
578 $versiondata['mtime'] = $value;
583 $versiondata[$key] = $value;
590 function SortByPageVersion ($a, $b) {
591 return $a['version'] - $b['version'];
594 function LoadFile (&$request, $filename, $text = false, $mtime = false)
596 if (!is_string($text)) {
598 $stat = stat($filename);
600 $text = implode("", file($filename));
603 if (! $request->getArg('start_debug'))
604 @set_time_limit(30); // Reset watchdog.
606 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
607 $basename = basename("/dummy/" . $filename);
610 $mtime = time(); // Last resort.
612 $default_pagename = rawurldecode($basename);
614 if ( ($parts = ParseMimeifiedPages($text)) ) {
615 usort($parts, 'SortByPageVersion');
616 foreach ($parts as $pageinfo)
617 SavePage($request, $pageinfo, sprintf(_("MIME file %s"),
618 $filename), $basename);
620 else if ( ($pageinfo = ParseSerializedPage($text, $default_pagename,
621 $request->getUser())) ) {
622 SavePage($request, $pageinfo, sprintf(_("Serialized file %s"),
623 $filename), $basename);
626 $user = $request->getUser();
628 // Assume plain text file.
629 $pageinfo = array('pagename' => $default_pagename,
630 'pagedata' => array(),
632 => array('author' => $user->getId()),
633 'content' => preg_replace('/[ \t\r]*\n/', "\n",
636 SavePage($request, $pageinfo, sprintf(_("plain file %s"), $filename),
641 function LoadZip (&$request, $zipfile, $files = false, $exclude = false) {
642 $zip = new ZipReader($zipfile);
643 while (list ($fn, $data, $attrib) = $zip->readFile()) {
644 // FIXME: basename("filewithnoslashes") seems to return
645 // garbage sometimes.
646 $fn = basename("/dummy/" . $fn);
647 if ( ($files && !in_array($fn, $files))
648 || ($exclude && in_array($fn, $exclude)) ) {
649 PrintXML(HTML::dt(WikiLink($fn)),
650 HTML::dd(_("Skipping")));
654 LoadFile($request, $fn, $data, $attrib['mtime']);
658 function LoadDir (&$request, $dirname, $files = false, $exclude = false) {
659 $fileset = new LimitedFileSet($dirname, $files, $exclude);
661 if (($skiplist = $fileset->getSkippedFiles())) {
662 PrintXML(HTML::dt(HTML::strong(_("Skipping"))));
664 foreach ($skiplist as $file)
665 $list->pushContent(HTML::li(WikiLink($file)));
666 PrintXML(HTML::dd($list));
669 // Defer HomePage loading until the end. If anything goes wrong
670 // the pages can still be loaded again.
671 $files = $fileset->getFiles();
672 if (in_array(HOME_PAGE, $files)) {
673 $files = array_diff($files, array(HOME_PAGE));
674 $files[] = HOME_PAGE;
676 foreach ($files as $file)
677 LoadFile($request, "$dirname/$file");
680 class LimitedFileSet extends FileSet {
681 function LimitedFileSet($dirname, $_include, $exclude) {
682 $this->_includefiles = $_include;
683 $this->_exclude = $exclude;
684 $this->_skiplist = array();
685 parent::FileSet($dirname);
688 function _filenameSelector($fn) {
689 $incl = &$this->_includefiles;
690 $excl = &$this->_exclude;
692 if ( ($incl && !in_array($fn, $incl))
693 || ($excl && in_array($fn, $excl)) ) {
694 $this->_skiplist[] = $fn;
701 function getSkippedFiles () {
702 return $this->_skiplist;
707 function IsZipFile ($filename_or_fd)
709 // See if it looks like zip file
710 if (is_string($filename_or_fd))
712 $fd = fopen($filename_or_fd, "rb");
713 $magic = fread($fd, 4);
718 $fpos = ftell($filename_or_fd);
719 $magic = fread($filename_or_fd, 4);
720 fseek($filename_or_fd, $fpos);
723 return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
727 function LoadAny (&$request, $file_or_dir, $files = false, $exclude = false)
729 // Try urlencoded filename for accented characters.
730 if (!file_exists($file_or_dir)) {
731 // Make sure there are slashes first to avoid confusing phps
732 // with broken dirname or basename functions.
733 // FIXME: windows uses \ and :
734 if (is_integer(strpos($file_or_dir, "/"))) {
735 $file_or_dir = FindFile($file_or_dir);
737 if (!file_exists($file_or_dir))
738 $file_or_dir = dirname($file_or_dir) . "/"
739 . urlencode(basename($file_or_dir));
741 // This is probably just a file.
742 $file_or_dir = urlencode($file_or_dir);
746 $type = filetype($file_or_dir);
747 if ($type == 'link') {
748 // For symbolic links, use stat() to determine
749 // the type of the underlying file.
750 list(,,$mode) = stat($file_or_dir);
751 $type = ($mode >> 12) & 017;
754 elseif ($type == 004)
759 $request->finish(fmt("Unable to load: %s", $file_or_dir));
761 else if ($type == 'dir') {
762 LoadDir($request, $file_or_dir, $files, $exclude);
764 else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
766 $request->finish(fmt("Bad file type: %s", $type));
768 else if (IsZipFile($file_or_dir)) {
769 LoadZip($request, $file_or_dir, $files, $exclude);
771 else /* if (!$files || in_array(basename($file_or_dir), $files)) */
773 LoadFile($request, $file_or_dir);
777 function LoadFileOrDir (&$request)
779 $source = $request->getArg('source');
780 StartLoadDump($request, fmt("Loading '%s'", HTML(dirname($source),
782 WikiLink(basename($source),
785 LoadAny($request, $source);
787 EndLoadDump($request);
790 function SetupWiki (&$request)
792 global $GenericPages, $LANG;
795 //FIXME: This is a hack (err, "interim solution")
796 // This is a bogo-bogo-login: Login without
797 // saving login information in session state.
798 // This avoids logging in the unsuspecting
799 // visitor as "The PhpWiki programming team".
801 // This really needs to be cleaned up...
802 // (I'm working on it.)
803 $real_user = $request->_user;
805 $request->_user = new _BogoUser(_("The PhpWiki programming team"));
808 $request->_user = new WikiUser($request, _("The PhpWiki programming team"),
811 StartLoadDump($request, _("Loading up virgin wiki"));
814 $pgsrc = FindLocalizedFile(WIKI_PGSRC);
815 $default_pgsrc = FindFile(DEFAULT_WIKI_PGSRC);
817 if ($default_pgsrc != $pgsrc)
818 LoadAny($request, $default_pgsrc, $GenericPages);
820 LoadAny($request, $pgsrc);
823 EndLoadDump($request);
826 function LoadPostFile (&$request)
828 $upload = $request->getUploadedFile('file');
831 $request->finish(_("No uploaded file to upload?")); // FIXME: more concise message
834 // Dump http headers.
835 StartLoadDump($request, sprintf(_("Uploading %s"), $upload->getName()));
838 $fd = $upload->open();
840 LoadZip($request, $fd, false, array(_("RecentChanges")));
842 LoadFile($request, $upload->getName(), $upload->getContents());
845 EndLoadDump($request);
849 $Log: not supported by cvs2svn $
850 Revision 1.90 2004/02/24 17:09:24 rurban
851 fixed \r\r\n with dumping on windows
853 Revision 1.88 2004/02/22 23:20:31 rurban
855 enhanced sortby handling in PageList
856 new button_heading th style (enabled),
857 added sortby and limit support to the db backends and plugins
858 for paging support (<<prev, next>> links on long lists)
860 Revision 1.87 2004/01/26 09:17:49 rurban
861 * changed stored pref representation as before.
862 the array of objects is 1) bigger and 2)
863 less portable. If we would import packed pref
864 objects and the object definition was changed, PHP would fail.
865 This doesn't happen with an simple array of non-default values.
866 * use $prefs->retrieve and $prefs->store methods, where retrieve
867 understands the interim format of array of objects also.
868 * simplified $prefs->get() and fixed $prefs->set()
869 * added $user->_userid and class '_WikiUser' portability functions
870 * fixed $user object ->_level upgrading, mostly using sessions.
871 this fixes yesterdays problems with loosing authorization level.
872 * fixed WikiUserNew::checkPass to return the _level
873 * fixed WikiUserNew::isSignedIn
874 * added explodePageList to class PageList, support sortby arg
875 * fixed UserPreferences for WikiUserNew
876 * fixed WikiPlugin for empty defaults array
877 * UnfoldSubpages: added pagename arg, renamed pages arg,
878 removed sort arg, support sortby arg
880 Revision 1.86 2003/12/02 16:18:26 carstenklapp
881 Minor enhancement: Provide more meaningful filenames for WikiDB zip
884 Revision 1.85 2003/11/30 18:18:13 carstenklapp
885 Minor code optimization: use include_once instead of require_once
886 inside functions that might not always called.
888 Revision 1.84 2003/11/26 20:47:47 carstenklapp
889 Redo bugfix: My last refactoring broke merge-edit & overwrite
890 functionality again, should be fixed now. Sorry.
892 Revision 1.83 2003/11/20 22:18:54 carstenklapp
893 New feature: h1 during merge-edit displays WikiLink to original page.
894 Internal changes: Replaced some hackish url-generation code in
895 function SavePage (for pgsrc merge-edit) with appropriate Button()
898 Revision 1.82 2003/11/18 19:48:01 carstenklapp
899 Fixed missing gettext _() for button name.
901 Revision 1.81 2003/11/18 18:28:35 carstenklapp
902 Bugfix: In the Load File function of PhpWikiAdministration: When doing
903 a "Merge Edit" or "Restore Anyway", page names containing accented
904 letters (such as locale/de/pgsrc/G%E4steBuch) would produce a file not
905 found error (Use FilenameForPage funtion to urlencode page names).
907 Revision 1.80 2003/03/07 02:46:57 dairiki
908 Omit checks for safe_mode before set_time_limit(). Just prefix the
909 set_time_limit() calls with @ so that they fail silently if not
912 Revision 1.79 2003/02/26 01:56:05 dairiki
913 Only zip pages with legal pagenames.
915 Revision 1.78 2003/02/24 02:05:43 dairiki
916 Fix "n bytes written" message when dumping HTML.
918 Revision 1.77 2003/02/21 04:12:05 dairiki
919 Minor fixes for new cached markup.
921 Revision 1.76 2003/02/16 19:47:17 dairiki
922 Update WikiDB timestamp when editing or deleting pages.
924 Revision 1.75 2003/02/15 03:04:30 dairiki
925 Fix for WikiUser constructor API change.
927 Revision 1.74 2003/02/15 02:18:04 dairiki
928 When default language was English (at least), pgsrc was being
931 LimitedFileSet: Fix typo/bug. ($include was being ignored.)
933 SetupWiki(): Fix bugs in loading of $GenericPages.
935 Revision 1.73 2003/01/28 21:09:17 zorloc
936 The get_cfg_var() function should only be used when one is
937 interested in the value from php.ini or similar. Use ini_get()
938 instead to get the effective value of a configuration variable.
941 Revision 1.72 2003/01/03 22:25:53 carstenklapp
942 Cosmetic fix to "Merge Edit" & "Overwrite" buttons. Added "The PhpWiki
943 programming team" as author when loading from pgsrc. Source
946 Revision 1.71 2003/01/03 02:48:05 carstenklapp
947 function SavePage: Added loadfile options for overwriting or merge &
948 compare a loaded pgsrc file with an existing page.
950 function LoadAny: Added a general error message when unable to load a
951 file instead of defaulting to "Bad file type".
960 // c-hanging-comment-ender-p: nil
961 // indent-tabs-mode: nil