2 rcs_id('$Id: loadsave.php,v 1.155 2007-09-12 19:40:41 rurban Exp $');
5 Copyright 1999,2000,2001,2002,2004,2005,2006,2007 $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
24 require_once("lib/ziplib.php");
25 require_once("lib/Template.php");
28 * ignore fatal errors during dump
30 function _dump_error_handler(&$error) {
31 if ($error->isFatal()) {
32 $error->errno = E_USER_WARNING;
35 return true; // Ignore error
37 if (preg_match('/Plugin/', $error->errstr))
40 // let the message come through: call the remaining handlers:
44 function StartLoadDump(&$request, $title, $html = '')
46 // MockRequest is from the unit testsuite, a faked request. (may be cmd-line)
47 // We are silent on unittests.
48 if (isa($request,'MockRequest'))
50 // FIXME: This is a hack. This really is the worst overall hack in phpwiki.
52 $html->pushContent('%BODY%');
53 $tmpl = Template('html', array('TITLE' => $title,
55 'CONTENT' => $html ? $html : '%BODY%'));
56 echo ereg_replace('%BODY%.*', '', $tmpl->getExpansion($html));
57 $request->chunkOutput();
59 // set marker for sendPageChangeNotification()
60 $request->_deferredPageChangeNotification = array();
63 function EndLoadDump(&$request)
65 if (isa($request,'MockRequest'))
67 $action = $request->getArg('action');
70 case 'zip': $label = _("ZIP files of database"); break;
71 case 'dumpserial': $label = _("Dump to directory"); break;
72 case 'upload': $label = _("Upload File"); break;
73 case 'loadfile': $label = _("Load File"); break;
74 case 'upgrade': $label = _("Upgrade"); break;
76 case 'ziphtml': $label = _("Dump pages as XHTML"); break;
78 if ($label) $label = str_replace(" ","_",$label);
79 if ($action == 'browse') // loading virgin
80 $pagelink = WikiLink(HOME_PAGE);
82 $pagelink = WikiLink(new WikiPageName(_("PhpWikiAdministration"),false,$label));
84 // do deferred sendPageChangeNotification()
85 if (!empty($request->_deferredPageChangeNotification)) {
86 $pages = $all_emails = $all_users = array();
87 foreach ($request->_deferredPageChangeNotification as $p) {
88 list($pagename, $emails, $userids) = $p;
90 $all_emails = array_unique(array_merge($all_emails, $emails));
91 $all_users = array_unique(array_merge($all_users, $userids));
93 $editedby = sprintf(_("Edited by: %s"), $request->_user->getId());
94 $content = "Loaded the following pages:\n" . join("\n", $pages);
95 if (mail(join(',',$all_emails),"[".WIKI_NAME."] "._("LoadDump"),
99 trigger_error(sprintf(_("PageChange Notification of %s sent to %s"),
100 join("\n",$pages), join(',',$all_users)), E_USER_NOTICE);
102 trigger_error(sprintf(_("PageChange Notification Error: Couldn't send %s to %s"),
103 join("\n",$pages), join(',',$all_users)), E_USER_WARNING);
108 unset($request->_deferredPageChangeNotification);
110 PrintXML(HTML::p(HTML::strong(_("Complete."))),
111 HTML::p(fmt("Return to %s", $pagelink)));
112 echo "</body></html>\n";
116 ////////////////////////////////////////////////////////////////
118 // Functions for dumping.
120 ////////////////////////////////////////////////////////////////
124 * http://www.nacs.uci.edu/indiv/ehood/MIME/2045/rfc2045.html
125 * http://www.faqs.org/rfcs/rfc2045.html
126 * (RFC 1521 has been superceeded by RFC 2045 & others).
128 * Also see http://www.faqs.org/rfcs/rfc2822.html
130 function MailifyPage ($page, $nversions = 1)
132 $current = $page->getCurrentRevision(false);
135 if (STRICT_MAILABLE_PAGEDUMPS) {
136 $from = defined('SERVER_ADMIN') ? SERVER_ADMIN : 'foo@bar';
137 //This is for unix mailbox format: (not RFC (2)822)
138 // $head .= "From $from " . CTime(time()) . "\r\n";
139 $head .= "Subject: " . rawurlencode($page->getName()) . "\r\n";
140 $head .= "From: $from (PhpWiki)\r\n";
141 // RFC 2822 requires only a Date: and originator (From:)
142 // field, however the obsolete standard RFC 822 also
143 // requires a destination field.
144 $head .= "To: $from (PhpWiki)\r\n";
146 $head .= "Date: " . Rfc2822DateTime($current->get('mtime')) . "\r\n";
147 $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n",
150 // This should just be entered by hand (or by script?)
151 // in the actual pgsrc files, since only they should have
153 //$head .= "X-Rcs-Id: \$Id\$\r\n";
155 $iter = $page->getAllRevisions();
157 while ($revision = $iter->next()) {
158 $parts[] = MimeifyPageRevision($page, $revision);
159 if ($nversions > 0 && count($parts) >= $nversions)
162 if (count($parts) > 1)
163 return $head . MimeMultipart($parts);
165 return $head . $parts[0];
169 * Compute filename to used for storing contents of a wiki page.
171 * Basically we do a rawurlencode() which encodes everything except
172 * ASCII alphanumerics and '.', '-', and '_'.
174 * But we also want to encode leading dots to avoid filenames like
175 * '.', and '..'. (Also, there's no point in generating "hidden" file
176 * names, like '.foo'.)
178 * We have to apply a different "/" logic for dumpserial, htmldump and zipdump.
179 * dirs are allowed for zipdump and htmldump, not for dumpserial
182 * @param $pagename string Pagename.
183 * @return string Filename for page.
185 function FilenameForPage ($pagename, $action = false)
187 $enc = rawurlencode($pagename);
190 $action = $request->getArg('action');
192 if ($action != 'dumpserial') { // zip, ziphtml, dumphtml
193 // For every %2F we will need to mkdir -p dirname($pagename)
194 $enc = preg_replace('/%2F/', '/', $enc);
196 $enc = preg_replace('/^\./', '%2E', $enc);
197 $enc = preg_replace('/%20/', ' ', $enc);
202 * The main() function which generates a zip archive of a PhpWiki.
204 * If $include_archive is false, only the current version of each page
205 * is included in the zip file; otherwise all archived versions are
208 function MakeWikiZip (&$request)
210 if ($request->getArg('include') == 'all') {
211 $zipname = WIKI_NAME . _("FullDump") . date('Ymd-Hi') . '.zip';
212 $include_archive = true;
215 $zipname = WIKI_NAME . _("LatestSnapshot") . date('Ymd-Hi') . '.zip';
216 $include_archive = false;
220 $zip = new ZipWriter("Created by PhpWiki " . PHPWIKI_VERSION, $zipname);
222 /* ignore fatals in plugins */
223 if (check_php_version(4,1)) {
224 global $ErrorManager;
225 $ErrorManager->pushErrorHandler(new WikiFunctionCb('_dump_error_handler'));
228 $dbi =& $request->_dbi;
229 $thispage = $request->getArg('pagename'); // for "Return to ..."
230 if ($exclude = $request->getArg('exclude')) { // exclude which pagenames
231 $excludeList = explodePageList($exclude);
233 $excludeList = array();
235 if ($pages = $request->getArg('pages')) { // which pagenames
236 if ($pages == '[]') // current page
238 $page_iter = new WikiDB_Array_PageIterator(explodePageList($pages));
240 $page_iter = $dbi->getAllPages(false,false,false,$excludeList);
242 $request_args = $request->args;
243 $timeout = (! $request->getArg('start_debug')) ? 30 : 240;
245 while ($page = $page_iter->next()) {
246 $request->args = $request_args; // some plugins might change them (esp. on POST)
247 longer_timeout($timeout); // Reset watchdog
249 $current = $page->getCurrentRevision();
250 if ($current->getVersion() == 0)
253 $pagename = $page->getName();
254 $wpn = new WikiPageName($pagename);
255 if (!$wpn->isValid())
257 if (in_array($page->getName(), $excludeList)) {
261 $attrib = array('mtime' => $current->get('mtime'),
263 if ($page->get('locked'))
264 $attrib['write_protected'] = 1;
266 if ($include_archive)
267 $content = MailifyPage($page, 0);
269 $content = MailifyPage($page);
271 $zip->addRegularFile( FilenameForPage($pagename),
275 if (check_php_version(4,1)) {
276 global $ErrorManager;
277 $ErrorManager->popErrorHandler();
281 function DumpToDir (&$request)
283 $directory = $request->getArg('directory');
284 if (empty($directory))
285 $directory = DEFAULT_DUMP_DIR; // See lib/plugin/WikiForm.php:87
286 if (empty($directory))
287 $request->finish(_("You must specify a directory to dump to"));
289 // see if we can access the directory the user wants us to use
290 if (! file_exists($directory)) {
291 if (! mkdir($directory, 0755))
292 $request->finish(fmt("Cannot create directory '%s'", $directory));
294 $html = HTML::p(fmt("Created directory '%s' for the page dump...",
297 $html = HTML::p(fmt("Using directory '%s'", $directory));
300 StartLoadDump($request, _("Dumping Pages"), $html);
302 $dbi =& $request->_dbi;
303 $thispage = $request->getArg('pagename'); // for "Return to ..."
304 if ($exclude = $request->getArg('exclude')) { // exclude which pagenames
305 $excludeList = explodePageList($exclude);
307 $excludeList = array();
309 if ($pages = $request->getArg('pages')) { // which pagenames
310 if ($pages == '[]') // current page
312 $page_iter = new WikiDB_Array_PageIterator(explodePageList($pages));
314 $page_iter = $dbi->getAllPages(false,false,false,$excludeList);
317 $request_args = $request->args;
318 $timeout = (! $request->getArg('start_debug')) ? 30 : 240;
320 while ($page = $page_iter->next()) {
321 $request->args = $request_args; // some plugins might change them (esp. on POST)
322 longer_timeout($timeout); // Reset watchdog
324 $pagename = $page->getName();
325 if (!isa($request,'MockRequest')) {
326 PrintXML(HTML::br(), $pagename, ' ... ');
330 if (in_array($pagename, $excludeList)) {
331 if (!isa($request, 'MockRequest')) {
332 PrintXML(_("Skipped."));
337 $filename = FilenameForPage($pagename);
339 if($page->getName() != $filename) {
340 $msg->pushContent(HTML::small(fmt("saved as %s", $filename)),
344 if ($request->getArg('include') == 'all')
345 $data = MailifyPage($page, 0);
347 $data = MailifyPage($page);
349 if ( !($fd = fopen($directory."/".$filename, "wb")) ) {
350 $msg->pushContent(HTML::strong(fmt("couldn't open file '%s' for writing",
351 "$directory/$filename")));
352 $request->finish($msg);
355 $num = fwrite($fd, $data, strlen($data));
356 $msg->pushContent(HTML::small(fmt("%s bytes written", $num)));
357 if (!isa($request, 'MockRequest')) {
361 assert($num == strlen($data));
365 EndLoadDump($request);
368 function _copyMsg($page, $smallmsg) {
369 if (!isa($GLOBALS['request'], 'MockRequest')) {
370 if ($page) $msg = HTML(HTML::br(), HTML($page), HTML::small($smallmsg));
371 else $msg = HTML::small($smallmsg);
377 function mkdir_p($pathname, $permission = 0777) {
378 $arr = explode("/", $pathname);
380 return mkdir($pathname, $permission);
382 $s = array_shift($arr);
384 foreach ($arr as $p) {
387 $ok = mkdir($curr, $permission);
389 if (!$ok) return FALSE;
395 * Dump all pages as XHTML to a directory, as pagename.html.
396 * Copies all used css files to the directory, all used images to a
397 * "images" subdirectory, and all used buttons to a "images/buttons" subdirectory.
398 * The webserver must have write permissions to these directories.
399 * chown httpd HTML_DUMP_DIR; chmod u+rwx HTML_DUMP_DIR
402 * @param string directory (optional) path to dump to. Default: HTML_DUMP_DIR
403 * @param string pages (optional) Comma-seperated of glob-style pagenames to dump.
404 * Also array of pagenames allowed.
405 * @param string exclude (optional) Comma-seperated of glob-style pagenames to exclude
407 function DumpHtmlToDir (&$request)
409 $directory = $request->getArg('directory');
410 if (empty($directory))
411 $directory = HTML_DUMP_DIR; // See lib/plugin/WikiForm.php:87
412 if (empty($directory))
413 $request->finish(_("You must specify a directory to dump to"));
415 // See if we can access the directory the user wants us to use
416 if (! file_exists($directory)) {
417 if (! mkdir($directory, 0755))
418 $request->finish(fmt("Cannot create directory '%s'", $directory));
420 $html = HTML::p(fmt("Created directory '%s' for the page dump...",
423 $html = HTML::p(fmt("Using directory '%s'", $directory));
425 $request->_TemplatesProcessed = array();
426 StartLoadDump($request, _("Dumping Pages"), $html);
427 $thispage = $request->getArg('pagename'); // for "Return to ..."
429 $dbi =& $request->_dbi;
430 if ($exclude = $request->getArg('exclude')) { // exclude which pagenames
431 $excludeList = explodePageList($exclude);
433 $excludeList = array('DebugAuthInfo', 'DebugGroupInfo', 'AuthInfo');
435 if ($pages = $request->getArg('pages')) { // which pagenames
436 if ($pages == '[]') // current page
438 $page_iter = new WikiDB_Array_PageIterator(explodePageList($pages));
439 // not at admin page: dump only the current page
440 } elseif ($thispage != _("PhpWikiAdministration")) {
441 $page_iter = new WikiDB_Array_PageIterator(array($thispage));
443 $page_iter = $dbi->getAllPages(false,false,false,$excludeList);
447 if (defined('HTML_DUMP_SUFFIX'))
448 $WikiTheme->HTML_DUMP_SUFFIX = HTML_DUMP_SUFFIX;
449 $WikiTheme->DUMP_MODE = 'HTML';
450 $_bodyAttr = @$WikiTheme->_MoreAttr['body'];
451 unset($WikiTheme->_MoreAttr['body']);
453 // check if the dumped file will be accessible from outside
454 $doc_root = $request->get("DOCUMENT_ROOT");
455 $ldir = NormalizeLocalFileName($directory);
456 $wikiroot = NormalizeLocalFileName('');
457 if (string_starts_with($ldir, $doc_root)) {
458 $link_prefix = substr($directory, strlen($doc_root))."/";
459 } elseif (string_starts_with($ldir, $wikiroot)) {
460 $link_prefix = NormalizeWebFileName(substr($directory, strlen($wikiroot)))."/";
464 $prefix = '/'; // . substr($doc_root,0,2); // add drive where apache is installed
466 $link_prefix = "file://".$prefix.$directory."/";
469 $request_args = $request->args;
470 $timeout = (! $request->getArg('start_debug')) ? 20 : 240;
471 $SAVE_RCS_IDS = $GLOBALS['RCS_IDS'];
472 @mkdir("$directory/images");
473 $doc_root = $request->get("DOCUMENT_ROOT");
475 while ($page = $page_iter->next()) {
476 $request->args = $request_args; // some plugins might change them (esp. on POST)
477 longer_timeout($timeout); // Reset watchdog
479 $pagename = $page->getName();
480 if (!isa($request,'MockRequest')) {
481 PrintXML(HTML::br(), $pagename, ' ... ');
484 if (in_array($pagename, $excludeList)) {
485 if (!isa($request,'MockRequest')) {
486 PrintXML(_("Skipped."));
492 $request->setArg('pagename', $pagename); // Template::_basepage fix
493 $filename = FilenameForPage($pagename) . $WikiTheme->HTML_DUMP_SUFFIX;
494 $revision = $page->getCurrentRevision();
495 $args = array('revision' => $revision,
496 'CONTENT' => $revision->getTransformedContent(),
497 'relative_base' => $relative_base);
498 // For every %2F will need to mkdir -p dirname($pagename)
499 if (preg_match("/(%2F|\/)/", $filename)) {
500 // mkdir -p and set relative base for subdir pages
501 $filename = preg_replace("/%2F/", "/", $filename);
502 $count = substr_count($filename, "/");
503 $dirname = dirname($filename);
504 mkdir_p($directory."/".$dirname);
505 // Fails with "XX / YY", "XX" is created, "XX / YY" cannot be written
506 if (isWindows()) // interesting Windows bug: cannot mkdir "bla "
507 $filename = preg_replace("/ \//", "/", $filename);
508 $relative_base = "../";
510 $relative_base .= "../";
513 $args['relative_base'] = $relative_base;
516 $template = new Template('browse', $request, $args);
518 $data = GeneratePageasXML($template, $pagename, $revision, $args);
520 $WikiTheme->other_images = array();
521 if (preg_match_all("/<img .*?src=\"(\/.+?)\"/", $data, $m)) {
522 // fix to local relative path for uploaded images, so that pdf will work
523 foreach ($m[1] as $img_file) {
524 $base = basename($img_file);
525 $data = str_replace('src="'.$img_file.'"','src="images/'.$base.'"', $data);
526 // resolve src from webdata to file
527 $src = $doc_root . $img_file;
528 if (file_exists($src) and $base) {
529 $target = "$directory/images/$base";
530 if (copy($src, $target)) {
531 _copyMsg($img_file, fmt("... copied to %s", $target));
533 _copyMsg($img_file, fmt("... not copied to %s", $target));
539 if ( !($fd = fopen($directory."/".$filename, "wb")) ) {
540 $msg->pushContent(HTML::strong(fmt("couldn't open file '%s' for writing",
541 "$directory/$filename")));
542 $request->finish($msg);
544 $len = strlen($data);
545 $num = fwrite($fd, $data, $len);
546 if ($page->getName() != $filename) {
547 $link = LinkURL($link_prefix.$filename, $filename);
548 $msg->pushContent(HTML::small(_("saved as "), $link, " ... "));
550 $msg->pushContent(HTML::small(fmt("%s bytes written", $num), "\n"));
551 if (!isa($request, 'MockRequest')) {
555 $request->chunkOutput();
557 assert($num == $len);
561 $request->_dbi->_cache->invalidate_cache($pagename);
562 unset ($request->_dbi->_cache->_pagedata_cache);
563 unset ($request->_dbi->_cache->_versiondata_cache);
564 unset ($request->_dbi->_cache->_glv_cache);
566 unset ($request->_dbi->_cache->_backend->_page_data);
569 unset($revision->_transformedContent);
571 unset($template->_request);
575 $GLOBALS['RCS_IDS'] = $SAVE_RCS_IDS;
579 if (!empty($WikiTheme->dumped_images) and is_array($WikiTheme->dumped_images)) {
580 // @mkdir("$directory/images");
581 foreach ($WikiTheme->dumped_images as $img_file) {
583 and ($from = $WikiTheme->_findFile($img_file, true))
586 $target = "$directory/images/".basename($img_file);
587 if (copy($WikiTheme->_path . $from, $target)) {
588 _copyMsg($from, fmt("... copied to %s", $target));
590 _copyMsg($from, fmt("... not copied to %s", $target));
593 _copyMsg($from, _("... not found"));
598 if (!empty($WikiTheme->dumped_buttons) and is_array($WikiTheme->dumped_buttons)) {
600 @mkdir("$directory/images/buttons");
601 foreach ($WikiTheme->dumped_buttons as $text => $img_file) {
603 and ($from = $WikiTheme->_findFile($img_file, true))
606 $target = "$directory/images/buttons/".basename($img_file);
607 if (copy($WikiTheme->_path . $from, $target)) {
608 _copyMsg($from, fmt("... copied to %s", $target));
610 _copyMsg($from, fmt("... not copied to %s", $target));
613 _copyMsg($from, _("... not found"));
617 if (!empty($WikiTheme->dumped_css) and is_array($WikiTheme->dumped_css)) {
618 foreach ($WikiTheme->dumped_css as $css_file) {
620 and ($from = $WikiTheme->_findFile(basename($css_file), true))
623 $target = "$directory/" . basename($css_file);
624 if (copy($WikiTheme->_path . $from, $target)) {
625 _copyMsg($from, fmt("... copied to %s", $target));
627 _copyMsg($from, fmt("... not copied to %s", $target));
629 // TODO: fix @import url(main.css);
631 _copyMsg($from, _("... not found"));
635 $WikiTheme->HTML_DUMP_SUFFIX = '';
636 $WikiTheme->DUMP_MODE = false;
637 $WikiTheme->_MoreAttr['body'] = $_bodyAttr;
639 $request->setArg('pagename',$thispage); // Template::_basepage fix
640 EndLoadDump($request);
643 /* Known problem: any plugins or other code which echo()s text will
644 * lead to a corrupted html zip file which may produce the following
645 * errors upon unzipping:
647 * warning [wikihtml.zip]: 2401 extra bytes at beginning or within zipfile
648 * file #58: bad zipfile offset (local header sig): 177561
649 * (attempting to re-compensate)
651 * However, the actual wiki page data should be unaffected.
653 function MakeWikiZipHtml (&$request)
655 $request->_TemplatesProcessed = array();
656 if ($request->getArg('zipname')) {
657 $zipname = basename($request->getArg('zipname'));
658 if (!preg_match("/\.zip$/i", $zipname))
660 $request->setArg('zipname', false);
662 $zipname = "wikihtml.zip";
664 $zip = new ZipWriter("Created by PhpWiki " . PHPWIKI_VERSION, $zipname);
665 $dbi =& $request->_dbi;
666 $thispage = $request->getArg('pagename'); // for "Return to ..."
667 if ($exclude = $request->getArg('exclude')) { // exclude which pagenames
668 $excludeList = explodePageList($exclude);
670 $excludeList = array();
672 if ($pages = $request->getArg('pages')) { // which pagenames
673 if ($pages == '[]') // current page
675 $page_iter = new WikiDB_Array_PageIterator(explodePageList($pages));
677 $page_iter = $dbi->getAllPages(false,false,false,$excludeList);
681 if (defined('HTML_DUMP_SUFFIX'))
682 $WikiTheme->HTML_DUMP_SUFFIX = HTML_DUMP_SUFFIX;
683 $WikiTheme->DUMP_MODE = 'ZIPHTML';
684 $WikiTheme->other_images = array();
685 $_bodyAttr = @$WikiTheme->_MoreAttr['body'];
686 unset($WikiTheme->_MoreAttr['body']);
688 /* ignore fatals in plugins */
689 if (check_php_version(4,1)) {
690 global $ErrorManager;
691 $ErrorManager->pushErrorHandler(new WikiFunctionCb('_dump_error_handler'));
694 $request_args = $request->args;
695 $timeout = (! $request->getArg('start_debug')) ? 20 : 240;
697 while ($page = $page_iter->next()) {
698 $request->args = $request_args; // some plugins might change them (esp. on POST)
699 longer_timeout($timeout); // Reset watchdog
701 $current = $page->getCurrentRevision();
702 if ($current->getVersion() == 0)
704 $pagename = $page->getName();
705 if (in_array($pagename, $excludeList)) {
709 $attrib = array('mtime' => $current->get('mtime'),
711 if ($page->get('locked'))
712 $attrib['write_protected'] = 1;
714 $request->setArg('pagename', $pagename); // Template::_basepage fix
715 $filename = FilenameForPage($pagename) . $WikiTheme->HTML_DUMP_SUFFIX;
716 $revision = $page->getCurrentRevision();
718 $transformedContent = $revision->getTransformedContent();
720 $template = new Template('browse', $request,
721 array('revision' => $revision,
722 'CONTENT' => $transformedContent));
724 $data = GeneratePageAsXML($template, $pagename);
726 // Detect local images. LinkImage et al...
727 // TODO: defer via Cached_InlinedImage
728 if (preg_match_all("/<img .*?src=\"(\/.+?)\"/", $data, $m)) {
729 foreach ($m[1] as $match) {
730 $WikiTheme->other_images[] = $match; //copy to images. no collisions yet.
731 $base = basename($match);
732 $data = str_replace('src="'.$match.'"','src="images/'.$base.'"', $data);
736 $zip->addRegularFile( $filename, $data, $attrib );
739 $request->_dbi->_cache->invalidate_cache($pagename);
740 unset ($request->_dbi->_cache->_pagedata_cache);
741 unset ($request->_dbi->_cache->_versiondata_cache);
742 unset ($request->_dbi->_cache->_glv_cache);
744 unset ($request->_dbi->_cache->_backend->_page_data);
746 unset($revision->_transformedContent);
748 unset($template->_request);
755 // Deal with theme css and theme images here.
756 if (!empty($WikiTheme->dumped_images) and is_array($WikiTheme->dumped_images)) {
757 // dirs are created automatically
758 //if ($WikiTheme->dumped_images) $zip->addRegularFile("images", "", $attrib);
759 foreach ($WikiTheme->dumped_images as $img_file) {
760 if (($from = $WikiTheme->_findFile($img_file, true)) and basename($from)) {
761 $target = "images/".basename($img_file);
762 if (check_php_version(4,3))
763 $zip->addRegularFile($target, file_get_contents($WikiTheme->_path . $from), $attrib);
765 $zip->addRegularFile($target, join('', file($WikiTheme->_path . $from)), $attrib);
769 if (!empty($WikiTheme->other_images) and is_array($WikiTheme->other_images)) {
770 $doc_root = $request->get("DOCUMENT_ROOT");
771 foreach ($WikiTheme->other_images as $img_file) {
772 // resolve src from webdata to file
773 $src = $doc_root . $img_file;
774 if (file_exists($src) and basename($src)) {
775 $target = "images/".basename($src);
776 if (check_php_version(4,3))
777 $zip->addRegularFile($target, file_get_contents($src), $attrib);
779 $zip->addRegularFile($target, join('', file($src)), $attrib);
783 if (!empty($WikiTheme->dumped_buttons) and is_array($WikiTheme->dumped_buttons)) {
784 //if ($WikiTheme->dumped_buttons) $zip->addRegularFile("images/buttons", "", $attrib);
785 foreach ($WikiTheme->dumped_buttons as $text => $img_file) {
786 if (($from = $WikiTheme->_findFile($img_file, true)) and basename($from)) {
787 $target = "images/buttons/".basename($img_file);
788 if (check_php_version(4,3))
789 $zip->addRegularFile($target, file_get_contents($WikiTheme->_path . $from), $attrib);
791 $zip->addRegularFile($target, join('', file($WikiTheme->_path . $from)), $attrib);
795 if (!empty($WikiTheme->dumped_css) and is_array($WikiTheme->dumped_css)) {
796 foreach ($WikiTheme->dumped_css as $css_file) {
797 if (($from = $WikiTheme->_findFile(basename($css_file), true)) and basename($from)) {
798 $target = basename($css_file);
799 if (check_php_version(4,3))
800 $zip->addRegularFile($target, file_get_contents($WikiTheme->_path . $from), $attrib);
802 $zip->addRegularFile($target, join('', file($WikiTheme->_path . $from)), $attrib);
808 if (check_php_version(4,1)) {
809 global $ErrorManager;
810 $ErrorManager->popErrorHandler();
812 $WikiTheme->HTML_DUMP_SUFFIX = '';
813 $WikiTheme->DUMP_MODE = false;
814 $WikiTheme->_MoreAttr['body'] = $_bodyAttr;
818 ////////////////////////////////////////////////////////////////
820 // Functions for restoring.
822 ////////////////////////////////////////////////////////////////
824 function SavePage (&$request, &$pageinfo, $source, $filename)
826 static $overwite_all = false;
827 $pagedata = $pageinfo['pagedata']; // Page level meta-data.
828 $versiondata = $pageinfo['versiondata']; // Revision level meta-data.
830 if (empty($pageinfo['pagename'])) {
831 PrintXML(HTML::dt(HTML::strong(_("Empty pagename!"))));
835 if (empty($versiondata['author_id']))
836 $versiondata['author_id'] = $versiondata['author'];
838 // remove invalid backend specific chars. utf8 issues mostly
839 $pagename_check = new WikiPagename($pageinfo['pagename']);
840 if (!$pagename_check->isValid()) {
841 PrintXML(HTML::dt(HTML::strong(_("Invalid pagename!")." ".$pageinfo['pagename'])));
844 $pagename = $pagename_check->getName();
845 $content = $pageinfo['content'];
847 if ($pagename == _("InterWikiMap"))
848 $content = _tryinsertInterWikiMap($content);
850 $dbi =& $request->_dbi;
851 $page = $dbi->getPage($pagename);
853 // Try to merge if updated pgsrc contents are different. This
854 // whole thing is hackish
856 // TODO: try merge unless:
857 // if (current contents = default contents && pgsrc_version >=
858 // pgsrc_version) then just upgrade this pgsrc
859 $needs_merge = false;
863 if ($request->getArg('merge')) {
866 else if ($request->getArg('overwrite')) {
870 $current = $page->getCurrentRevision();
872 $edit = $request->getArg('edit');
874 if (isset($edit['keep_old'])) {
878 elseif (isset($edit['overwrite'])) {
882 elseif ( $current and (! $current->hasDefaultContents())
883 && ($current->getPackedContent() != $content) )
885 include_once('lib/editpage.php');
886 $request->setArg('pagename', $pagename);
887 $v = $current->getVersion();
888 $request->setArg('revision', $current->getVersion());
889 $p = new LoadFileConflictPageEditor($request);
890 $p->_content = $content;
891 $p->_currentVersion = $v - 1;
892 $p->editPage($saveFailed = true);
893 return; //early return
897 foreach ($pagedata as $key => $value) {
899 $page->set($key, $value);
904 $mesg->pushContent(' ', fmt("from %s", $source));
908 //FIXME: This should not happen! (empty vdata, corrupt cache or db)
909 $current = $page->getCurrentRevision();
911 if ($current->getVersion() == 0) {
912 $mesg->pushContent(' - ', _("New page"));
916 if ( (! $current->hasDefaultContents())
917 && ($current->getPackedContent() != $content) ) {
919 $mesg->pushContent(' ',
920 fmt("has edit conflicts - overwriting anyway"));
922 if (substr_count($source, 'pgsrc')) {
923 $versiondata['author'] = _("The PhpWiki programming team");
924 // but leave authorid as userid who loaded the file
928 if (isset($edit['keep_old'])) {
929 $mesg->pushContent(' ', fmt("keep old"));
931 $mesg->pushContent(' ', fmt("has edit conflicts - skipped"));
932 $needs_merge = true; // hackish, to display the buttons
937 else if ($current->getPackedContent() == $content
938 && $current->get('author') == $versiondata['author']) {
939 // The page metadata is already changed, we don't need a new revision.
940 // This was called previously "is identical to current version %d - skipped"
941 // which is wrong, since the pagedata was stored, not skipped.
942 $mesg->pushContent(' ',
943 fmt("content is identical to current version %d - no new revision created",
944 $current->getVersion()));
951 // in case of failures print the culprit:
952 if (!isa($request,'MockRequest')) {
953 PrintXML(HTML::dt(WikiLink($pagename))); flush();
955 $new = $page->save($content, WIKIDB_FORCE_CREATE, $versiondata);
957 $mesg->pushContent(' ', fmt("- saved to database as version %d",
958 $new->getVersion()));
962 // hackish, $source contains needed path+filename
963 $f = str_replace(sprintf(_("MIME file %s"), ''), '', $f);
964 $f = str_replace(sprintf(_("Serialized file %s"), ''), '', $f);
965 $f = str_replace(sprintf(_("plain file %s"), ''), '', $f);
966 //check if uploaded file? they pass just the content, but the file is gone
969 $meb = Button(array('action' => 'loadfile',
973 _("PhpWikiAdministration"),
975 $owb = Button(array('action' => 'loadfile',
979 _("PhpWikiAdministration"),
981 $mesg->pushContent(' ', $meb, " ", $owb);
982 if (!$overwite_all) {
983 $args = $request->getArgs();
984 $args['overwrite'] = 1;
987 _("PhpWikiAdministration"),
989 $mesg->pushContent(HTML::div(array('class' => 'hint'), $owb));
990 $overwite_all = true;
993 $mesg->pushContent(HTML::em(_(" Sorry, cannot merge.")));
997 if (!isa($request,'MockRequest')) {
999 PrintXML(HTML::dt(HTML::em(WikiLink($pagename))), $mesg);
1006 // action=revert (by diff)
1007 function RevertPage (&$request)
1010 $pagename = $request->getArg('pagename');
1011 $version = $request->getArg('version');
1013 PrintXML(HTML::dt(fmt("Revert")," ",WikiLink($pagename)),
1014 HTML::dd(_("missing required version argument")));
1017 $dbi =& $request->_dbi;
1018 $page = $dbi->getPage($pagename);
1019 $current = $page->getCurrentRevision();
1020 $currversion = $current->getVersion();
1021 if ($currversion == 0) {
1022 $mesg->pushContent(' ', _("no page content"));
1023 PrintXML(HTML::dt(fmt("Revert")," ",WikiLink($pagename)),
1028 if ($currversion == $version) {
1029 $mesg->pushContent(' ', _("same version page"));
1030 PrintXML(HTML::dt(fmt("Revert")," ",WikiLink($pagename)),
1035 if ($request->getArg('cancel')) {
1036 $mesg->pushContent(' ', _("Cancelled"));
1037 PrintXML(HTML::dt(fmt("Revert")," ",WikiLink($pagename)),
1042 if (!$request->getArg('verify')) {
1043 $mesg->pushContent(HTML::br(),
1046 HTML::form(array('action' => $request->getPostURL(),
1047 'method' => 'post'),
1048 HiddenInputs($request->getArgs(), false, array('verify')),
1049 HiddenInputs(array('verify' => 1)),
1050 Button('submit:verify', _("Yes"), 'button'),
1051 HTML::Raw(' '),
1052 Button('submit:cancel', _("Cancel"), 'button')),
1054 $rev = $page->getRevision($version);
1055 $html = HTML(HTML::dt(fmt("Revert %s to version $version", WikiLink($pagename))),
1057 $rev->getTransformedContent());
1058 $template = Template('browse',
1059 array('CONTENT' => $html));
1060 GeneratePage($template, $pagename, $rev);
1061 $request->checkValidators();
1065 $rev = $page->getRevision($version);
1066 $content = $rev->getPackedContent();
1067 $versiondata = $rev->_data;
1068 $versiondata['summary'] = sprintf(_("revert to version %d"), $version);
1069 $new = $page->save($content, $currversion + 1, $versiondata);
1072 $pagelink = WikiLink($pagename);
1073 $mesg->pushContent(fmt("Revert: %s", $pagelink),
1074 fmt("- version %d saved to database as version %d",
1075 $version, $new->getVersion()));
1076 // Force browse of current page version.
1077 $request->setArg('version', false);
1078 $template = Template('savepage', array());
1079 $template->replace('CONTENT', $new->getTransformedContent());
1081 GeneratePage($template, $mesg, $new);
1085 function _tryinsertInterWikiMap($content) {
1087 if (strpos($content, "<verbatim>")) {
1088 //$error_html = " The newly loaded pgsrc already contains a verbatim block.";
1091 if (!$goback && !defined('INTERWIKI_MAP_FILE')) {
1092 $error_html = sprintf(" "._("%s: not defined"), "INTERWIKI_MAP_FILE");
1095 $mapfile = FindFile(INTERWIKI_MAP_FILE,1);
1096 if (!$goback && !file_exists($mapfile)) {
1097 $error_html = sprintf(" "._("%s: file not found"), INTERWIKI_MAP_FILE);
1101 if (!empty($error_html))
1102 trigger_error(_("Default InterWiki map file not loaded.")
1103 . $error_html, E_USER_NOTICE);
1107 // if loading from virgin setup do echo, otherwise trigger_error E_USER_NOTICE
1108 if (!isa($GLOBALS['request'], 'MockRequest'))
1109 echo sprintf(_("Loading InterWikiMap from external file %s."), $mapfile),"<br />";
1111 $fd = fopen ($mapfile, "rb");
1112 $data = fread ($fd, filesize($mapfile));
1114 $content = $content . "\n<verbatim>\n$data</verbatim>\n";
1118 function ParseSerializedPage($text, $default_pagename, $user)
1120 if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
1123 $pagehash = unserialize($text);
1125 // Split up pagehash into four parts:
1128 // page-level meta-data
1129 // revision-level meta-data
1131 if (!defined('FLAG_PAGE_LOCKED'))
1132 define('FLAG_PAGE_LOCKED', 1);
1133 $pageinfo = array('pagedata' => array(),
1134 'versiondata' => array());
1136 $pagedata = &$pageinfo['pagedata'];
1137 $versiondata = &$pageinfo['versiondata'];
1139 // Fill in defaults.
1140 if (empty($pagehash['pagename']))
1141 $pagehash['pagename'] = $default_pagename;
1142 if (empty($pagehash['author'])) {
1143 $pagehash['author'] = $user->getId();
1146 foreach ($pagehash as $key => $value) {
1151 $pageinfo[$key] = $value;
1154 $pageinfo[$key] = join("\n", $value);
1157 if (($value & FLAG_PAGE_LOCKED) != 0)
1158 $pagedata['locked'] = 'yes';
1162 $pagedata[$key] = $value;
1166 $pagedata['perm'] = ParseMimeifiedPerm($value);
1168 case 'lastmodified':
1169 $versiondata['mtime'] = $value;
1174 $versiondata[$key] = $value;
1178 if (empty($pagehash['charset']))
1179 $pagehash['charset'] = 'iso-8859-1';
1180 // compare to target charset
1181 if (strtolower($pagehash['charset']) != strtolower($GLOBALS['charset'])) {
1182 $pageinfo['content'] = charset_convert($params['charset'], $GLOBALS['charset'], $pageinfo['content']);
1183 $pageinfo['pagename'] = charset_convert($params['charset'], $GLOBALS['charset'], $pageinfo['pagename']);
1188 function SortByPageVersion ($a, $b) {
1189 return $a['version'] - $b['version'];
1193 * Security alert! We should not allow to import config.ini into our wiki (or from a sister wiki?)
1194 * because the sql passwords are in plaintext there. And the webserver must be able to read it.
1195 * Detected by Santtu Jarvi.
1197 function LoadFile (&$request, $filename, $text = false, $mtime = false)
1199 if (preg_match("/config$/", dirname($filename)) // our or other config
1200 and preg_match("/config.*\.ini/", basename($filename))) // backups and other versions also
1202 trigger_error(sprintf("Refused to load %s", $filename), E_USER_WARNING);
1205 if (!is_string($text)) {
1207 $stat = stat($filename);
1209 $text = implode("", file($filename));
1212 if (! $request->getArg('start_debug')) @set_time_limit(30); // Reset watchdog
1213 else @set_time_limit(240);
1215 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
1216 $basename = basename("/dummy/" . $filename);
1219 $mtime = time(); // Last resort.
1221 // DONE: check source - target charset for content and pagename
1222 // but only for pgsrc'ed content, not from the browser.
1224 $default_pagename = rawurldecode($basename);
1225 if ( ($parts = ParseMimeifiedPages($text)) ) {
1226 if (count($parts) > 1)
1227 $overwrite = $request->getArg('overwrite');
1228 usort($parts, 'SortByPageVersion');
1229 foreach ($parts as $pageinfo) {
1231 if (count($parts) > 1)
1232 $request->setArg('overwrite', 1);
1233 SavePage($request, $pageinfo, sprintf(_("MIME file %s"),
1234 $filename), $basename);
1236 if (count($parts) > 1)
1238 $request->setArg('overwrite', $overwrite);
1240 unset($request->_args['overwrite']);
1242 else if ( ($pageinfo = ParseSerializedPage($text, $default_pagename,
1243 $request->getUser())) ) {
1244 SavePage($request, $pageinfo, sprintf(_("Serialized file %s"),
1245 $filename), $basename);
1249 $user = $request->getUser();
1251 $file_charset = 'iso-8859-1';
1252 // compare to target charset
1253 if ($file_charset != strtolower($GLOBALS['charset'])) {
1254 $text = charset_convert($file_charset, $GLOBALS['charset'], $text);
1255 $default_pagename = charset_convert($file_charset, $GLOBALS['charset'], $default_pagename);
1258 // Assume plain text file.
1259 $pageinfo = array('pagename' => $default_pagename,
1260 'pagedata' => array(),
1262 => array('author' => $user->getId()),
1263 'content' => preg_replace('/[ \t\r]*\n/', "\n",
1266 SavePage($request, $pageinfo, sprintf(_("plain file %s"), $filename),
1271 function LoadZip (&$request, $zipfile, $files = false, $exclude = false) {
1272 $zip = new ZipReader($zipfile);
1273 $timeout = (! $request->getArg('start_debug')) ? 20 : 120;
1274 while (list ($fn, $data, $attrib) = $zip->readFile()) {
1275 // FIXME: basename("filewithnoslashes") seems to return
1276 // garbage sometimes.
1277 $fn = basename("/dummy/" . $fn);
1278 if ( ($files && !in_array($fn, $files))
1279 || ($exclude && in_array($fn, $exclude)) ) {
1280 PrintXML(HTML::dt(WikiLink($fn)),
1281 HTML::dd(_("Skipping")));
1285 longer_timeout($timeout); // longer timeout per page
1286 LoadFile($request, $fn, $data, $attrib['mtime']);
1290 function LoadDir (&$request, $dirname, $files = false, $exclude = false) {
1291 $fileset = new LimitedFileSet($dirname, $files, $exclude);
1293 if (!$files and ($skiplist = $fileset->getSkippedFiles())) {
1294 PrintXML(HTML::dt(HTML::strong(_("Skipping"))));
1296 foreach ($skiplist as $file)
1297 $list->pushContent(HTML::li(WikiLink($file)));
1298 PrintXML(HTML::dd($list));
1301 // Defer HomePage loading until the end. If anything goes wrong
1302 // the pages can still be loaded again.
1303 $files = $fileset->getFiles();
1304 if (in_array(HOME_PAGE, $files)) {
1305 $files = array_diff($files, array(HOME_PAGE));
1306 $files[] = HOME_PAGE;
1308 $timeout = (! $request->getArg('start_debug')) ? 20 : 120;
1309 foreach ($files as $file) {
1310 longer_timeout($timeout); // longer timeout per page
1311 if (substr($file,-1,1) != '~') // refuse to load backup files
1312 LoadFile($request, "$dirname/$file");
1316 class LimitedFileSet extends FileSet {
1317 function LimitedFileSet($dirname, $_include, $exclude) {
1318 $this->_includefiles = $_include;
1319 $this->_exclude = $exclude;
1320 $this->_skiplist = array();
1321 parent::FileSet($dirname);
1324 function _filenameSelector($fn) {
1325 $incl = &$this->_includefiles;
1326 $excl = &$this->_exclude;
1328 if ( ($incl && !in_array($fn, $incl))
1329 || ($excl && in_array($fn, $excl)) ) {
1330 $this->_skiplist[] = $fn;
1337 function getSkippedFiles () {
1338 return $this->_skiplist;
1343 function IsZipFile ($filename_or_fd)
1345 // See if it looks like zip file
1346 if (is_string($filename_or_fd))
1348 $fd = fopen($filename_or_fd, "rb");
1349 $magic = fread($fd, 4);
1354 $fpos = ftell($filename_or_fd);
1355 $magic = fread($filename_or_fd, 4);
1356 fseek($filename_or_fd, $fpos);
1359 return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
1363 function LoadAny (&$request, $file_or_dir, $files = false, $exclude = false)
1365 // Try urlencoded filename for accented characters.
1366 if (!file_exists($file_or_dir)) {
1367 // Make sure there are slashes first to avoid confusing phps
1368 // with broken dirname or basename functions.
1369 // FIXME: windows uses \ and :
1370 if (is_integer(strpos($file_or_dir, "/"))) {
1371 $newfile = FindFile($file_or_dir, true);
1372 // Panic. urlencoded by the browser (e.g. San%20Diego => San Diego)
1374 $file_or_dir = dirname($file_or_dir) . "/"
1375 . rawurlencode(basename($file_or_dir));
1377 // This is probably just a file.
1378 $file_or_dir = rawurlencode($file_or_dir);
1382 $type = filetype($file_or_dir);
1383 if ($type == 'link') {
1384 // For symbolic links, use stat() to determine
1385 // the type of the underlying file.
1386 list(,,$mode) = stat($file_or_dir);
1387 $type = ($mode >> 12) & 017;
1390 elseif ($type == 004)
1395 $request->finish(fmt("Empty or not existing source. Unable to load: %s", $file_or_dir));
1397 else if ($type == 'dir') {
1398 LoadDir($request, $file_or_dir, $files, $exclude);
1400 else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
1402 $request->finish(fmt("Bad file type: %s", $type));
1404 else if (IsZipFile($file_or_dir)) {
1405 LoadZip($request, $file_or_dir, $files, $exclude);
1407 else /* if (!$files || in_array(basename($file_or_dir), $files)) */
1409 LoadFile($request, $file_or_dir);
1413 function LoadFileOrDir (&$request)
1415 $source = $request->getArg('source');
1416 $finder = new FileFinder;
1417 $source = $finder->slashifyPath($source);
1418 $page = rawurldecode(basename($source));
1419 StartLoadDump($request, fmt("Loading '%s'",
1420 HTML(dirname($source),
1421 dirname($source) ? "/" : "",
1422 WikiLink($page,'auto'))));
1424 LoadAny($request, $source);
1426 EndLoadDump($request);
1430 * HomePage was not found so first-time install is supposed to run.
1431 * - import all pgsrc pages.
1432 * - Todo: installer interface to edit config/config.ini settings
1433 * - Todo: ask for existing old index.php to convert to config/config.ini
1434 * - Todo: theme-specific pages:
1435 * blog - HomePage, ADMIN_USER/Blogs
1437 function SetupWiki (&$request)
1439 global $GenericPages, $LANG;
1441 //FIXME: This is a hack (err, "interim solution")
1442 // This is a bogo-bogo-login: Login without
1443 // saving login information in session state.
1444 // This avoids logging in the unsuspecting
1445 // visitor as "The PhpWiki programming team".
1447 // This really needs to be cleaned up...
1448 // (I'm working on it.)
1449 $real_user = $request->_user;
1450 if (ENABLE_USER_NEW)
1451 $request->_user = new _BogoUser(_("The PhpWiki programming team"));
1454 $request->_user = new WikiUser($request, _("The PhpWiki programming team"),
1457 StartLoadDump($request, _("Loading up virgin wiki"));
1460 $pgsrc = FindLocalizedFile(WIKI_PGSRC);
1461 $default_pgsrc = FindFile(DEFAULT_WIKI_PGSRC);
1463 $request->setArg('overwrite', true);
1464 if ($default_pgsrc != $pgsrc) {
1465 LoadAny($request, $default_pgsrc, $GenericPages);
1467 $request->setArg('overwrite', false);
1468 LoadAny($request, $pgsrc);
1469 $dbi =& $request->_dbi;
1471 // Ensure that all mandatory pages are loaded
1472 $finder = new FileFinder;
1473 foreach (array_merge(explode(':','Help/OldTextFormattingRules:Help/TextFormattingRules:PhpWikiAdministration'),
1474 $GLOBALS['AllActionPages'],
1475 array(constant('HOME_PAGE'))) as $f)
1477 $page = gettext($f);
1478 $epage = urlencode($page);
1479 if (! $dbi->isWikiPage($page) ) {
1480 // translated version provided?
1481 if ($lf = FindLocalizedFile($pgsrc . $finder->_pathsep . $epage, 1)) {
1482 LoadAny($request, $lf);
1483 } else { // load english version of required action page
1484 LoadAny($request, FindFile(DEFAULT_WIKI_PGSRC . $finder->_pathsep . urlencode($f)));
1488 if (! $dbi->isWikiPage($page)) {
1489 trigger_error(sprintf("Mandatory file %s couldn't be loaded!", $page),
1495 $pagename = _("InterWikiMap");
1496 $map = $dbi->getPage($pagename);
1497 $map->set('locked', true);
1498 PrintXML(HTML::dt(HTML::em(WikiLink($pagename))), HTML::dd("locked"));
1499 EndLoadDump($request);
1502 function LoadPostFile (&$request)
1504 $upload = $request->getUploadedFile('file');
1507 $request->finish(_("No uploaded file to upload?")); // FIXME: more concise message
1510 // Dump http headers.
1511 StartLoadDump($request, sprintf(_("Uploading %s"), $upload->getName()));
1514 $fd = $upload->open();
1516 LoadZip($request, $fd, false, array(_("RecentChanges")));
1518 LoadFile($request, $upload->getName(), $upload->getContents());
1521 EndLoadDump($request);
1525 $Log: not supported by cvs2svn $
1526 Revision 1.154 2007/08/10 22:00:43 rurban
1528 We have to apply a different "/" logic for dumpserial, htmldump and
1529 zipdump. dirs are allowed for zipdump and htmldump, not for dumpserial.
1531 Revision 1.153 2007/05/28 20:54:40 rurban
1532 fix DumpToHtml creating dirs
1534 Revision 1.152 2007/05/01 16:22:41 rurban
1535 lock InterWikiMap on init
1537 Revision 1.151 2007/02/17 14:17:34 rurban
1538 only media=print css for htmldump and pdf
1540 Revision 1.150 2007/01/20 15:53:42 rurban
1541 Use WikiPagename treatment for imported pagenames
1543 Revision 1.149 2007/01/03 21:25:10 rurban
1544 Use convert_charset()
1546 Revision 1.148 2007/01/02 13:21:57 rurban
1547 omit want_content if not necessary. support keep_old and overwrite buttons
1549 Revision 1.147 2006/12/22 17:44:15 rurban
1550 support importing foreign charsets. e.g latin1 => utf8
1552 Revision 1.146 2006/12/17 18:35:23 rurban
1553 Create the right subdirectory name, urlencoded.
1555 Revision 1.145 2006/09/06 06:01:18 rurban
1556 support loadfile multipart archives automatically
1558 Revision 1.144 2006/08/25 22:06:13 rurban
1559 args fix to pass $args to the template
1561 Revision 1.143 2006/08/25 21:48:39 rurban
1564 Revision 1.142 2006/03/19 17:16:32 rurban
1565 remove remaining cruft
1567 Revision 1.141 2006/03/19 17:11:32 rurban
1568 add verify to RevertPage, display reverted page as template
1570 Revision 1.140 2006/03/07 20:45:43 rurban
1571 wikihash for php-5.1
1573 Revision 1.139 2005/08/27 18:02:43 rurban
1574 fix and expand pages
1576 Revision 1.138 2005/08/27 09:39:10 rurban
1577 dumphtml when not at admin page: dump the current or given page
1579 Revision 1.137 2005/01/30 23:14:38 rurban
1582 Revision 1.136 2005/01/25 07:07:24 rurban
1583 remove body tags in html dumps, add css and images to zipdumps, simplify printing
1585 Revision 1.135 2004/12/26 17:17:25 rurban
1586 announce dumps - mult.requests to avoid request::finish, e.g. LinkDatabase, PdfOut, ...
1588 Revision 1.134 2004/12/20 16:05:01 rurban
1589 gettext msg unification
1591 Revision 1.133 2004/12/08 12:57:41 rurban
1592 page-specific timeouts for long multi-page requests
1594 Revision 1.132 2004/12/08 01:18:33 rurban
1595 Disallow loading config*.ini files. Detected by Santtu Jarvi.
1597 Revision 1.131 2004/11/30 17:48:38 rurban
1600 Revision 1.130 2004/11/25 08:28:12 rurban
1601 dont fatal on missing css or imgfiles and actually print the miss
1603 Revision 1.129 2004/11/25 08:11:40 rurban
1604 pass exclude to the get_all_pages backend
1606 Revision 1.128 2004/11/16 16:16:44 rurban
1607 enable Overwrite All for upgrade
1609 Revision 1.127 2004/11/01 10:43:57 rurban
1610 seperate PassUser methods into seperate dir (memory usage)
1611 fix WikiUser (old) overlarge data session
1612 remove wikidb arg from various page class methods, use global ->_dbi instead
1615 Revision 1.126 2004/10/16 15:13:39 rurban
1616 new [Overwrite All] button
1618 Revision 1.125 2004/10/14 19:19:33 rurban
1619 loadsave: check if the dumped file will be accessible from outside.
1620 and some other minor fixes. (cvsclient native not yet ready)
1622 Revision 1.124 2004/10/04 23:44:28 rurban
1623 for older or CGI phps
1625 Revision 1.123 2004/09/25 16:26:54 rurban
1626 deferr notifies (to be improved)
1628 Revision 1.122 2004/09/17 14:25:45 rurban
1631 Revision 1.121 2004/09/08 13:38:00 rurban
1632 improve loadfile stability by using markup=2 as default for undefined markup-style.
1633 use more refs for huge objects.
1634 fix debug=static issue in WikiPluginCached
1636 Revision 1.120 2004/07/08 19:04:42 rurban
1637 more unittest fixes (file backend, metadata RatingsDb)
1639 Revision 1.119 2004/07/08 15:23:59 rurban
1640 less verbose for tests
1642 Revision 1.118 2004/07/08 13:50:32 rurban
1643 various unit test fixes: print error backtrace on _DEBUG_TRACE; allusers fix; new PHPWIKI_NOMAIN constant for omitting the mainloop
1645 Revision 1.117 2004/07/02 09:55:58 rurban
1646 more stability fixes: new DISABLE_GETIMAGESIZE if your php crashes when loading LinkIcons: failing getimagesize in old phps; blockparser stabilized
1648 Revision 1.116 2004/07/01 09:05:41 rurban
1649 support pages and exclude arguments for all 4 dump methods
1651 Revision 1.115 2004/07/01 08:51:22 rurban
1652 dumphtml: added exclude, print pagename before processing
1654 Revision 1.114 2004/06/28 12:51:41 rurban
1655 improved dumphtml and virgin setup
1657 Revision 1.113 2004/06/27 10:26:02 rurban
1658 oci8 patch by Philippe Vanhaesendonck + some ADODB notes+fixes
1660 Revision 1.112 2004/06/25 14:29:20 rurban
1661 WikiGroup refactoring:
1662 global group attached to user, code for not_current user.
1663 improved helpers for special groups (avoid double invocations)
1664 new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
1665 fixed a XHTML validation error on userprefs.tmpl
1667 Revision 1.111 2004/06/21 16:38:55 rurban
1668 fixed the StartLoadDump html argument hack.
1670 Revision 1.110 2004/06/21 16:22:30 rurban
1671 add DEFAULT_DUMP_DIR and HTML_DUMP_DIR constants, for easier cmdline dumps,
1672 fixed dumping buttons locally (images/buttons/),
1673 support pages arg for dumphtml,
1674 optional directory arg for dumpserial + dumphtml,
1675 fix a AllPages warning,
1676 show dump warnings/errors on DEBUG,
1677 don't warn just ignore on wikilens pagelist columns, if not loaded.
1678 RateIt pagelist column is called "rating", not "ratingwidget" (Dan?)
1680 Revision 1.109 2004/06/17 11:31:05 rurban
1681 jump back to label after dump/upgrade
1683 Revision 1.108 2004/06/16 12:43:01 rurban
1684 4.0.6 cannot use this errorhandler (not found)
1686 Revision 1.107 2004/06/14 11:31:37 rurban
1687 renamed global $Theme to $WikiTheme (gforge nameclash)
1688 inherit PageList default options from PageList
1689 default sortby=pagename
1690 use options in PageList_Selectable (limit, sortby, ...)
1691 added action revert, with button at action=diff
1692 added option regex to WikiAdminSearchReplace
1694 Revision 1.106 2004/06/13 13:54:25 rurban
1695 Catch fatals on the four dump calls (as file and zip, as html and mimified)
1696 FoafViewer: Check against external requirements, instead of fatal.
1697 Change output for xhtmldumps: using file:// urls to the local fs.
1698 Catch SOAP fatal by checking for GOOGLE_LICENSE_KEY
1699 Import GOOGLE_LICENSE_KEY and FORTUNE_DIR from config.ini.
1701 Revision 1.105 2004/06/08 19:48:16 rurban
1702 fixed foreign setup: no ugly skipped msg for the GenericPages, load english actionpages if translated not found
1704 Revision 1.104 2004/06/08 13:51:57 rurban
1707 Revision 1.103 2004/06/08 10:54:46 rurban
1708 better acl dump representation, read back acl and owner
1710 Revision 1.102 2004/06/06 16:58:51 rurban
1711 added more required ActionPages for foreign languages
1712 install now english ActionPages if no localized are found. (again)
1713 fixed default anon user level to be 0, instead of -1
1714 (wrong "required administrator to view this page"...)
1716 Revision 1.101 2004/06/04 20:32:53 rurban
1717 Several locale related improvements suggested by Pierrick Meignen
1718 LDAP fix by John Cole
1719 reenable admin check without ENABLE_PAGEPERM in the admin plugins
1721 Revision 1.100 2004/05/02 21:26:38 rurban
1722 limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
1723 because they will not survive db sessions, if too large.
1724 extended action=upgrade
1725 some WikiTranslation button work
1726 revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
1727 some temp. session debug statements
1729 Revision 1.99 2004/05/02 15:10:07 rurban
1730 new finally reliable way to detect if /index.php is called directly
1731 and if to include lib/main.php
1732 new global AllActionPages
1733 SetupWiki now loads all mandatory pages: HOME_PAGE, action pages, and warns if not.
1734 WikiTranslation what=buttons for Carsten to create the missing MacOSX buttons
1735 PageGroupTestOne => subpages
1736 renamed PhpWikiRss to PhpWikiRecentChanges
1737 more docs, default configs, ...
1739 Revision 1.98 2004/04/29 23:25:12 rurban
1740 re-ordered locale init (as in 1.3.9)
1741 fixed loadfile with subpages, and merge/restore anyway
1742 (sf.net bug #844188)
1744 Revision 1.96 2004/04/19 23:13:03 zorloc
1745 Connect the rest of PhpWiki to the IniConfig system. Also the keyword regular expression is not a config setting
1747 Revision 1.95 2004/04/18 01:11:52 rurban
1748 more numeric pagename fixes.
1749 fixed action=upload with merge conflict warnings.
1750 charset changed from constant to global (dynamic utf-8 switching)
1752 Revision 1.94 2004/03/14 16:36:37 rurban
1753 dont load backup files
1755 Revision 1.93 2004/02/26 03:22:05 rurban
1756 also copy css and images with XHTML Dump
1758 Revision 1.92 2004/02/26 02:25:54 rurban
1759 fix empty and #-anchored links in XHTML Dumps
1761 Revision 1.91 2004/02/24 17:19:37 rurban
1762 debugging helpers only
1764 Revision 1.90 2004/02/24 17:09:24 rurban
1765 fixed \r\r\n with dumping on windows
1767 Revision 1.88 2004/02/22 23:20:31 rurban
1768 fixed DumpHtmlToDir,
1769 enhanced sortby handling in PageList
1770 new button_heading th style (enabled),
1771 added sortby and limit support to the db backends and plugins
1772 for paging support (<<prev, next>> links on long lists)
1774 Revision 1.87 2004/01/26 09:17:49 rurban
1775 * changed stored pref representation as before.
1776 the array of objects is 1) bigger and 2)
1777 less portable. If we would import packed pref
1778 objects and the object definition was changed, PHP would fail.
1779 This doesn't happen with an simple array of non-default values.
1780 * use $prefs->retrieve and $prefs->store methods, where retrieve
1781 understands the interim format of array of objects also.
1782 * simplified $prefs->get() and fixed $prefs->set()
1783 * added $user->_userid and class '_WikiUser' portability functions
1784 * fixed $user object ->_level upgrading, mostly using sessions.
1785 this fixes yesterdays problems with loosing authorization level.
1786 * fixed WikiUserNew::checkPass to return the _level
1787 * fixed WikiUserNew::isSignedIn
1788 * added explodePageList to class PageList, support sortby arg
1789 * fixed UserPreferences for WikiUserNew
1790 * fixed WikiPlugin for empty defaults array
1791 * UnfoldSubpages: added pagename arg, renamed pages arg,
1792 removed sort arg, support sortby arg
1794 Revision 1.86 2003/12/02 16:18:26 carstenklapp
1795 Minor enhancement: Provide more meaningful filenames for WikiDB zip
1798 Revision 1.85 2003/11/30 18:18:13 carstenklapp
1799 Minor code optimization: use include_once instead of require_once
1800 inside functions that might not always called.
1802 Revision 1.84 2003/11/26 20:47:47 carstenklapp
1803 Redo bugfix: My last refactoring broke merge-edit & overwrite
1804 functionality again, should be fixed now. Sorry.
1806 Revision 1.83 2003/11/20 22:18:54 carstenklapp
1807 New feature: h1 during merge-edit displays WikiLink to original page.
1808 Internal changes: Replaced some hackish url-generation code in
1809 function SavePage (for pgsrc merge-edit) with appropriate Button()
1812 Revision 1.82 2003/11/18 19:48:01 carstenklapp
1813 Fixed missing gettext _() for button name.
1815 Revision 1.81 2003/11/18 18:28:35 carstenklapp
1816 Bugfix: In the Load File function of PhpWikiAdministration: When doing
1817 a "Merge Edit" or "Restore Anyway", page names containing accented
1818 letters (such as locale/de/pgsrc/G%E4steBuch) would produce a file not
1819 found error (Use FilenameForPage funtion to urlencode page names).
1821 Revision 1.80 2003/03/07 02:46:57 dairiki
1822 Omit checks for safe_mode before set_time_limit(). Just prefix the
1823 set_time_limit() calls with @ so that they fail silently if not
1826 Revision 1.79 2003/02/26 01:56:05 dairiki
1827 Only zip pages with legal pagenames.
1829 Revision 1.78 2003/02/24 02:05:43 dairiki
1830 Fix "n bytes written" message when dumping HTML.
1832 Revision 1.77 2003/02/21 04:12:05 dairiki
1833 Minor fixes for new cached markup.
1835 Revision 1.76 2003/02/16 19:47:17 dairiki
1836 Update WikiDB timestamp when editing or deleting pages.
1838 Revision 1.75 2003/02/15 03:04:30 dairiki
1839 Fix for WikiUser constructor API change.
1841 Revision 1.74 2003/02/15 02:18:04 dairiki
1842 When default language was English (at least), pgsrc was being
1845 LimitedFileSet: Fix typo/bug. ($include was being ignored.)
1847 SetupWiki(): Fix bugs in loading of $GenericPages.
1849 Revision 1.73 2003/01/28 21:09:17 zorloc
1850 The get_cfg_var() function should only be used when one is
1851 interested in the value from php.ini or similar. Use ini_get()
1852 instead to get the effective value of a configuration variable.
1855 Revision 1.72 2003/01/03 22:25:53 carstenklapp
1856 Cosmetic fix to "Merge Edit" & "Overwrite" buttons. Added "The PhpWiki
1857 programming team" as author when loading from pgsrc. Source
1860 Revision 1.71 2003/01/03 02:48:05 carstenklapp
1861 function SavePage: Added loadfile options for overwriting or merge &
1862 compare a loaded pgsrc file with an existing page.
1864 function LoadAny: Added a general error message when unable to load a
1865 file instead of defaulting to "Bad file type".
1873 // c-basic-offset: 4
1874 // c-hanging-comment-ender-p: nil
1875 // indent-tabs-mode: nil