5 * Copyright 1999,2000,2001,2002,2004,2005,2006,2007 $ThePhpWikiProgrammingTeam
6 * Copyright 2008-2010 Marc-Etienne Vargenau, Alcatel-Lucent
8 * This file is part of PhpWiki.
10 * PhpWiki is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * PhpWiki is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 require_once("lib/ziplib.php");
26 require_once("lib/Template.php");
29 * ignore fatal errors during dump
31 function _dump_error_handler($error) {
32 if ($error->isFatal()) {
33 $error->errno = E_USER_WARNING;
36 return true; // Ignore error
38 if (preg_match('/Plugin/', $error->errstr))
41 // let the message come through: call the remaining handlers:
45 function StartLoadDump(&$request, $title, $html = '')
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'))
51 // FIXME: This is a hack. This really is the worst overall hack in phpwiki.
53 $html->pushContent('%BODY%');
54 $tmpl = Template('html', array('TITLE' => $title,
56 'CONTENT' => $html ? $html : '%BODY%'));
57 echo preg_replace('/%BODY%.*/s', '', $tmpl->getExpansion($html));
58 $request->chunkOutput();
60 // set marker for sendPageChangeNotification()
61 $request->_deferredPageChangeNotification = array();
64 function EndLoadDump(&$request)
68 if (isa($request,'MockRequest'))
70 $action = $request->getArg('action');
73 case 'zip': $label = _("ZIP files of database"); break;
74 case 'dumpserial': $label = _("Dump to directory"); break;
75 case 'upload': $label = _("Upload File"); break;
76 case 'loadfile': $label = _("Load File"); break;
77 case 'upgrade': $label = _("Upgrade"); break;
79 case 'ziphtml': $label = _("Dump pages as XHTML"); break;
81 if ($label) $label = str_replace(" ","_",$label);
82 if ($action == 'browse') // loading virgin
83 $pagelink = WikiLink(HOME_PAGE);
85 $pagelink = WikiLink(new WikiPageName(_("PhpWikiAdministration"),false,$label));
87 // do deferred sendPageChangeNotification()
88 if (!empty($request->_deferredPageChangeNotification)) {
89 $pages = $all_emails = $all_users = array();
90 foreach ($request->_deferredPageChangeNotification as $p) {
91 list($pagename, $emails, $userids) = $p;
93 $all_emails = array_unique(array_merge($all_emails, $emails));
94 $all_users = array_unique(array_merge($all_users, $userids));
96 $editedby = sprintf(_("Edited by: %s"), $request->_user->getId());
97 $content = "Loaded the following pages:\n" . join("\n", $pages);
98 if (mail(join(',',$all_emails),"[".WIKI_NAME."] "._("LoadDump"),
102 trigger_error(sprintf(_("PageChange Notification of %s sent to %s"),
103 join("\n",$pages), join(',',$all_users)), E_USER_NOTICE);
105 trigger_error(sprintf(_("PageChange Notification Error: Couldn't send %s to %s"),
106 join("\n",$pages), join(',',$all_users)), E_USER_WARNING);
111 unset($request->_deferredPageChangeNotification);
113 PrintXML(HTML::p(HTML::strong(_("Complete."))),
114 HTML::p(fmt("Return to %s", $pagelink)));
115 // Ugly hack to get valid XHTML code
116 if (isa($WikiTheme, 'WikiTheme_fusionforge')) {
121 } else if (isa($WikiTheme, 'WikiTheme_Sidebar')
122 or isa($WikiTheme, 'WikiTheme_MonoBook')) {
127 } else if (isa($WikiTheme, 'WikiTheme_wikilens')) {
132 } else if (isa($WikiTheme, 'WikiTheme_blog')) {
135 } else if (isa($WikiTheme, 'WikiTheme_Crao')
136 or isa($WikiTheme, 'WikiTheme_Hawaiian')
137 or isa($WikiTheme, 'WikiTheme_MacOSX')
138 or isa($WikiTheme, 'WikiTheme_shamino_com')
139 or isa($WikiTheme, 'WikiTheme_smaller')) {
142 echo "</body></html>\n";
145 ////////////////////////////////////////////////////////////////
147 // Functions for dumping.
149 ////////////////////////////////////////////////////////////////
153 * http://www.nacs.uci.edu/indiv/ehood/MIME/2045/rfc2045.html
154 * http://www.faqs.org/rfcs/rfc2045.html
155 * (RFC 1521 has been superceeded by RFC 2045 & others).
157 * Also see http://www.faqs.org/rfcs/rfc2822.html
159 function MailifyPage ($page, $nversions = 1)
161 $current = $page->getCurrentRevision(false);
164 if (STRICT_MAILABLE_PAGEDUMPS) {
165 $from = defined('SERVER_ADMIN') ? SERVER_ADMIN : 'foo@bar';
166 //This is for unix mailbox format: (not RFC (2)822)
167 // $head .= "From $from " . CTime(time()) . "\r\n";
168 $head .= "Subject: " . rawurlencode($page->getName()) . "\r\n";
169 $head .= "From: $from (PhpWiki)\r\n";
170 // RFC 2822 requires only a Date: and originator (From:)
171 // field, however the obsolete standard RFC 822 also
172 // requires a destination field.
173 $head .= "To: $from (PhpWiki)\r\n";
175 $head .= "Date: " . Rfc2822DateTime($current->get('mtime')) . "\r\n";
176 $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n",
179 // This should just be entered by hand (or by script?)
180 // in the actual pgsrc files, since only they should have
182 //$head .= "X-Rcs-Id: \$Id\$\r\n";
184 $iter = $page->getAllRevisions();
186 while ($revision = $iter->next()) {
187 $parts[] = MimeifyPageRevision($page, $revision);
188 if ($nversions > 0 && count($parts) >= $nversions)
191 if (count($parts) > 1)
192 return $head . MimeMultipart($parts);
194 return $head . $parts[0];
198 * Compute filename to used for storing contents of a wiki page.
200 * Basically we do a rawurlencode() which encodes everything except
201 * ASCII alphanumerics and '.', '-', and '_'.
203 * But we also want to encode leading dots to avoid filenames like
204 * '.', and '..'. (Also, there's no point in generating "hidden" file
205 * names, like '.foo'.)
207 * We have to apply a different "/" logic for dumpserial, htmldump and zipdump.
208 * dirs are allowed for zipdump and htmldump, not for dumpserial
211 * @param $pagename string Pagename.
212 * @return string Filename for page.
214 function FilenameForPage ($pagename, $action = false)
216 $enc = rawurlencode($pagename);
219 $action = $request->getArg('action');
221 if ($action != 'dumpserial') { // zip, ziphtml, dumphtml
222 // For every %2F we will need to mkdir -p dirname($pagename)
223 $enc = preg_replace('/%2F/', '/', $enc);
225 $enc = preg_replace('/^\./', '%2E', $enc);
226 $enc = preg_replace('/%20/', ' ', $enc);
227 $enc = preg_replace('/\.$/', '%2E', $enc);
232 * The main() function which generates a zip archive of a PhpWiki.
234 * If $include_archive is false, only the current version of each page
235 * is included in the zip file; otherwise all archived versions are
238 function MakeWikiZip (&$request)
240 global $ErrorManager;
241 if ($request->getArg('include') == 'all') {
242 $zipname = WIKI_NAME . _("FullDump") . date('Ymd-Hi') . '.zip';
243 $include_archive = true;
246 $zipname = WIKI_NAME . _("LatestSnapshot") . date('Ymd-Hi') . '.zip';
247 $include_archive = false;
249 $include_empty = false;
250 if ($request->getArg('include') == 'empty') {
251 $include_empty = true;
254 $zip = new ZipWriter("Created by PhpWiki " . PHPWIKI_VERSION, $zipname);
256 /* ignore fatals in plugins */
257 $ErrorManager->pushErrorHandler(new WikiFunctionCb('_dump_error_handler'));
259 $dbi =& $request->_dbi;
260 $thispage = $request->getArg('pagename'); // for "Return to ..."
261 if ($exclude = $request->getArg('exclude')) { // exclude which pagenames
262 $excludeList = explodePageList($exclude);
264 $excludeList = array();
266 if ($pages = $request->getArg('pages')) { // which pagenames
267 if ($pages == '[]') // current page
269 $page_iter = new WikiDB_Array_PageIterator(explodePageList($pages));
271 $page_iter = $dbi->getAllPages(false,false,false,$excludeList);
273 $request_args = $request->args;
274 $timeout = (! $request->getArg('start_debug')) ? 30 : 240;
276 while ($page = $page_iter->next()) {
277 $request->args = $request_args; // some plugins might change them (esp. on POST)
278 longer_timeout($timeout); // Reset watchdog
280 $current = $page->getCurrentRevision();
281 if ($current->getVersion() == 0)
284 $pagename = $page->getName();
285 $wpn = new WikiPageName($pagename);
286 if (!$wpn->isValid())
288 if (in_array($page->getName(), $excludeList)) {
292 $attrib = array('mtime' => $current->get('mtime'),
294 if ($page->get('locked'))
295 $attrib['write_protected'] = 1;
297 if ($include_archive)
298 $content = MailifyPage($page, 0);
300 $content = MailifyPage($page);
302 $zip->addRegularFile( FilenameForPage($pagename),
307 $ErrorManager->popErrorHandler();
310 function DumpToDir (&$request)
312 $directory = $request->getArg('directory');
313 if (empty($directory))
314 $directory = DEFAULT_DUMP_DIR; // See lib/plugin/WikiForm.php:87
315 if (empty($directory))
316 $request->finish(_("You must specify a directory to dump to"));
318 // see if we can access the directory the user wants us to use
319 if (! file_exists($directory)) {
320 if (! mkdir($directory, 0755))
321 $request->finish(fmt("Cannot create directory '%s'", $directory));
323 $html = HTML::p(fmt("Created directory '%s' for the page dump...",
326 $html = HTML::p(fmt("Using directory '%s'", $directory));
329 StartLoadDump($request, _("Dumping Pages"), $html);
331 $dbi =& $request->_dbi;
332 $thispage = $request->getArg('pagename'); // for "Return to ..."
333 if ($exclude = $request->getArg('exclude')) { // exclude which pagenames
334 $excludeList = explodePageList($exclude);
336 $excludeList = array();
338 $include_empty = false;
339 if ($request->getArg('include') == 'empty') {
340 $include_empty = true;
342 if ($pages = $request->getArg('pages')) { // which pagenames
343 if ($pages == '[]') // current page
345 $page_iter = new WikiDB_Array_PageIterator(explodePageList($pages));
347 $page_iter = $dbi->getAllPages($include_empty,false,false,$excludeList);
350 $request_args = $request->args;
351 $timeout = (! $request->getArg('start_debug')) ? 30 : 240;
353 while ($page = $page_iter->next()) {
354 $request->args = $request_args; // some plugins might change them (esp. on POST)
355 longer_timeout($timeout); // Reset watchdog
357 $pagename = $page->getName();
358 if (!isa($request,'MockRequest')) {
359 PrintXML(HTML::br(), $pagename, ' ... ');
363 if (in_array($pagename, $excludeList)) {
364 if (!isa($request, 'MockRequest')) {
365 PrintXML(_("Skipped."));
370 $filename = FilenameForPage($pagename);
372 if($page->getName() != $filename) {
373 $msg->pushContent(HTML::small(fmt("saved as %s", $filename)),
377 if ($request->getArg('include') == 'all')
378 $data = MailifyPage($page, 0);
380 $data = MailifyPage($page);
382 if ( !($fd = fopen($directory."/".$filename, "wb")) ) {
383 $msg->pushContent(HTML::strong(fmt("couldn't open file '%s' for writing",
384 "$directory/$filename")));
385 $request->finish($msg);
388 $num = fwrite($fd, $data, strlen($data));
389 $msg->pushContent(HTML::small(fmt("%s bytes written", $num)));
390 if (!isa($request, 'MockRequest')) {
394 assert($num == strlen($data));
398 EndLoadDump($request);
401 function _copyMsg($page, $smallmsg) {
402 if (!isa($GLOBALS['request'], 'MockRequest')) {
403 if ($page) $msg = HTML(HTML::br(), HTML($page), HTML::small($smallmsg));
404 else $msg = HTML::small($smallmsg);
410 function mkdir_p($pathname, $permission = 0777) {
411 $arr = explode("/", $pathname);
413 return mkdir($pathname, $permission);
415 $s = array_shift($arr);
417 foreach ($arr as $p) {
420 $ok = mkdir($curr, $permission);
422 if (!$ok) return FALSE;
428 * Dump all pages as XHTML to a directory, as pagename.html.
429 * Copies all used css files to the directory, all used images to a
430 * "images" subdirectory, and all used buttons to a "images/buttons" subdirectory.
431 * The webserver must have write permissions to these directories.
432 * chown httpd HTML_DUMP_DIR; chmod u+rwx HTML_DUMP_DIR
435 * @param string directory (optional) path to dump to. Default: HTML_DUMP_DIR
436 * @param string pages (optional) Comma-seperated of glob-style pagenames to dump.
437 * Also array of pagenames allowed.
438 * @param string exclude (optional) Comma-seperated of glob-style pagenames to exclude
440 function DumpHtmlToDir (&$request)
443 $directory = $request->getArg('directory');
444 if (empty($directory))
445 $directory = HTML_DUMP_DIR; // See lib/plugin/WikiForm.php:87
446 if (empty($directory))
447 $request->finish(_("You must specify a directory to dump to"));
449 // See if we can access the directory the user wants us to use
450 if (! file_exists($directory)) {
451 if (! mkdir($directory, 0755))
452 $request->finish(fmt("Cannot create directory '%s'", $directory));
454 $html = HTML::p(fmt("Created directory '%s' for the page dump...",
457 $html = HTML::p(fmt("Using directory '%s'", $directory));
459 StartLoadDump($request, _("Dumping Pages"), $html);
460 $thispage = $request->getArg('pagename'); // for "Return to ..."
462 $dbi =& $request->_dbi;
463 if ($exclude = $request->getArg('exclude')) { // exclude which pagenames
464 $excludeList = explodePageList($exclude);
466 $excludeList = array('DebugAuthInfo', 'DebugGroupInfo', 'AuthInfo');
468 if ($pages = $request->getArg('pages')) { // which pagenames
469 if ($pages == '[]') // current page
471 $page_iter = new WikiDB_Array_generic_iter(explodePageList($pages));
472 // not at admin page: dump only the current page
473 } elseif ($thispage != _("PhpWikiAdministration")) {
474 $page_iter = new WikiDB_Array_generic_iter(array($thispage));
476 $page_iter = $dbi->getAllPages(false,false,false,$excludeList);
479 $WikiTheme->DUMP_MODE = 'HTML';
480 _DumpHtmlToDir($directory, $page_iter, $request->getArg('exclude'));
481 $WikiTheme->DUMP_MODE = false;
483 $request->setArg('pagename',$thispage); // Template::_basepage fix
484 EndLoadDump($request);
487 /* Known problem: any plugins or other code which echo()s text will
488 * lead to a corrupted html zip file which may produce the following
489 * errors upon unzipping:
491 * warning [wikihtml.zip]: 2401 extra bytes at beginning or within zipfile
492 * file #58: bad zipfile offset (local header sig): 177561
493 * (attempting to re-compensate)
495 * However, the actual wiki page data should be unaffected.
497 function MakeWikiZipHtml (&$request)
500 if ($request->getArg('zipname')) {
501 $zipname = basename($request->getArg('zipname'));
502 if (!preg_match("/\.zip$/i", $zipname))
504 $request->setArg('zipname', false);
506 $zipname = "wikihtml.zip";
508 $zip = new ZipWriter("Created by PhpWiki " . PHPWIKI_VERSION, $zipname);
509 $dbi =& $request->_dbi;
510 $thispage = $request->getArg('pagename'); // for "Return to ..."
511 if ($pages = $request->getArg('pages')) { // which pagenames
512 if ($pages == '[]') // current page
514 $page_iter = new WikiDB_Array_generic_iter(explodePageList($pages));
516 $page_iter = $dbi->getAllPages(false,false,false,$request->getArg('exclude'));
519 $WikiTheme->DUMP_MODE = 'ZIPHTML';
520 _DumpHtmlToDir($zip, $page_iter, $request->getArg('exclude'));
521 $WikiTheme->DUMP_MODE = false;
525 * Internal html dumper. Used for dumphtml, ziphtml and pdf
527 function _DumpHtmlToDir ($target, $page_iter, $exclude = false)
529 global $WikiTheme, $request, $ErrorManager;
530 $silent = true; $zip = false; $directory = false;
531 if ($WikiTheme->DUMP_MODE == 'HTML') {
532 $directory = $target;
534 } elseif ($WikiTheme->DUMP_MODE == 'PDFHTML') {
535 $directory = $target;
536 } elseif (is_object($target)) { // $WikiTheme->DUMP_MODE == 'ZIPHTML'
540 $request->_TemplatesProcessed = array();
541 if ($exclude) { // exclude which pagenames
542 $excludeList = explodePageList($exclude);
544 $excludeList = array('DebugAuthInfo', 'DebugGroupInfo', 'AuthInfo');
546 $WikiTheme->VALID_LINKS = array();
547 if ($request->getArg('format')) { // pagelist
548 $page_iter_sav = $page_iter;
549 foreach ($page_iter_sav->asArray() as $handle) {
550 $WikiTheme->VALID_LINKS[] = is_string($handle) ? $handle : $handle->getName();
552 $page_iter_sav->reset();
555 if (defined('HTML_DUMP_SUFFIX')) {
556 $WikiTheme->HTML_DUMP_SUFFIX = HTML_DUMP_SUFFIX;
558 if (isset($WikiTheme->_MoreAttr['body'])) {
559 $_bodyAttr = $WikiTheme->_MoreAttr['body'];
560 unset($WikiTheme->_MoreAttr['body']);
563 $ErrorManager->pushErrorHandler(new WikiFunctionCb('_dump_error_handler'));
565 // check if the dumped file will be accessible from outside
566 $doc_root = $request->get("DOCUMENT_ROOT");
567 if ($WikiTheme->DUMP_MODE == 'HTML') {
568 $ldir = NormalizeLocalFileName($directory);
569 $wikiroot = NormalizeLocalFileName('');
570 if (string_starts_with($ldir, $doc_root)) {
571 $link_prefix = substr($directory, strlen($doc_root))."/";
572 } elseif (string_starts_with($ldir, $wikiroot)) {
573 $link_prefix = NormalizeWebFileName(substr($directory, strlen($wikiroot)))."/";
577 $prefix = '/'; // . substr($doc_root,0,2); // add drive where apache is installed
579 $link_prefix = "file://".$prefix.$directory."/";
585 $request_args = $request->args;
586 $timeout = (! $request->getArg('start_debug')) ? 60 : 240;
589 $directory = str_replace("\\", "/", $directory); // no Win95 support.
590 if (!is_dir("$directory/images"))
591 mkdir("$directory/images");
595 $already_images = array();
597 while ($page = $page_iter->next()) {
598 if (is_string($page)) {
600 $page = $request->_dbi->getPage($pagename);
602 $pagename = $page->getName();
604 if (empty($firstpage)) $firstpage = $pagename;
605 if (array_key_exists($pagename, $already))
607 $already[$pagename] = 1;
608 $current = $page->getCurrentRevision();
609 //if ($current->getVersion() == 0)
612 $request->args = $request_args; // some plugins might change them (esp. on POST)
613 longer_timeout($timeout); // Reset watchdog
616 $attrib = array('mtime' => $current->get('mtime'),
618 if ($page->get('locked'))
619 $attrib['write_protected'] = 1;
620 } elseif (!$silent) {
621 if (!isa($request,'MockRequest')) {
622 PrintXML(HTML::br(), $pagename, ' ... ');
626 if (in_array($pagename, $excludeList)) {
627 if (!$silent and !isa($request,'MockRequest')) {
628 PrintXML(_("Skipped."));
634 if ($WikiTheme->DUMP_MODE == 'PDFHTML')
635 $request->setArg('action', 'pdf'); // to omit cache headers
636 $request->setArg('pagename', $pagename); // Template::_basepage fix
637 $filename = FilenameForPage($pagename) . $WikiTheme->HTML_DUMP_SUFFIX;
638 $args = array('revision' => $current,
639 'CONTENT' => $current->getTransformedContent(),
640 'relative_base' => $relative_base);
641 // For every %2F will need to mkdir -p dirname($pagename)
642 if (preg_match("/(%2F|\/)/", $filename)) {
643 // mkdir -p and set relative base for subdir pages
644 $filename = preg_replace("/%2F/", "/", $filename);
645 $count = substr_count($filename, "/");
646 $dirname = dirname($filename);
648 mkdir_p($directory."/".$dirname);
649 // Fails with "XX / YY", "XX" is created, "XX / YY" cannot be written
650 // if (isWindows()) // interesting Windows bug: cannot mkdir "bla "
651 // Since dumps needs to be copied, we have to disallow this for all platforms.
652 $filename = preg_replace("/ \//", "/", $filename);
653 $relative_base = "../";
655 $relative_base .= "../";
658 $args['relative_base'] = $relative_base;
662 $DUMP_MODE = $WikiTheme->DUMP_MODE;
663 $data = GeneratePageasXML(new Template('browse', $request, $args),
664 $pagename, $current, $args);
665 $WikiTheme->DUMP_MODE = $DUMP_MODE;
667 if (preg_match_all("/<img .*?src=\"(\/.+?)\"/", $data, $m)) {
668 // fix to local relative path for uploaded images, so that pdf will work
669 foreach ($m[1] as $img_file) {
670 $base = basename($img_file);
671 $data = str_replace('src="'.$img_file.'"','src="images/'.$base.'"', $data);
672 if (array_key_exists($img_file, $already_images))
674 $already_images[$img_file] = 1;
675 // resolve src from webdata to file
676 $src = $doc_root . $img_file;
677 if (file_exists($src) and $base) {
679 $target = "$directory/images/$base";
680 if (copy($src, $target)) {
682 _copyMsg($img_file, fmt("... copied to %s", $target));
685 _copyMsg($img_file, fmt("... not copied to %s", $target));
688 $target = "images/$base";
689 $zip->addSrcFile($target, $src);
696 $outfile = $directory."/".$filename;
697 if ( !($fd = fopen($outfile, "wb")) ) {
698 $msg->pushContent(HTML::strong(fmt("couldn't open file '%s' for writing",
700 $request->finish($msg);
702 $len = strlen($data);
703 $num = fwrite($fd, $data, $len);
704 if ($pagename != $filename) {
705 $link = LinkURL($link_prefix.$filename, $filename);
706 $msg->pushContent(HTML::small(_("saved as "), $link, " ... "));
708 $msg->pushContent(HTML::small(fmt("%s bytes written", $num), "\n"));
710 if (!isa($request, 'MockRequest')) {
714 $request->chunkOutput();
716 assert($num == $len);
718 $outfiles[] = $outfile;
720 $zip->addRegularFile($filename, $data, $attrib);
724 $request->_dbi->_cache->invalidate_cache($pagename);
725 unset ($request->_dbi->_cache->_pagedata_cache);
726 unset ($request->_dbi->_cache->_versiondata_cache);
727 unset ($request->_dbi->_cache->_glv_cache);
729 unset ($request->_dbi->_cache->_backend->_page_data);
732 unset($current->_transformedContent);
734 if (!empty($template)) {
735 unset($template->_request);
742 $attrib = false; //array('is_ascii' => 0);
743 if (!empty($WikiTheme->dumped_images) and is_array($WikiTheme->dumped_images)) {
744 // @mkdir("$directory/images");
745 foreach ($WikiTheme->dumped_images as $img_file) {
746 if (array_key_exists($img_file, $already_images))
748 $already_images[$img_file] = 1;
750 and ($from = $WikiTheme->_findFile($img_file, true))
754 $target = "$directory/images/".basename($from);
756 copy($WikiTheme->_path . $from, $target);
758 if (copy($WikiTheme->_path . $from, $target)) {
759 _copyMsg($from, fmt("... copied to %s", $target));
761 _copyMsg($from, fmt("... not copied to %s", $target));
765 $target = "images/".basename($from);
766 $zip->addSrcFile($target, $WikiTheme->_path . $from);
768 } elseif (!$silent) {
769 _copyMsg($from, _("... not found"));
774 if (!empty($WikiTheme->dumped_buttons)
775 and is_array($WikiTheme->dumped_buttons))
778 if ($directory && !is_dir("$directory/images/buttons"))
779 mkdir("$directory/images/buttons");
780 foreach ($WikiTheme->dumped_buttons as $text => $img_file) {
781 if (array_key_exists($img_file, $already_images))
783 $already_images[$img_file] = 1;
785 and ($from = $WikiTheme->_findFile($img_file, true))
789 $target = "$directory/images/buttons/".basename($from);
791 copy($WikiTheme->_path . $from, $target);
793 if (copy($WikiTheme->_path . $from, $target)) {
794 _copyMsg($from, fmt("... copied to %s", $target));
796 _copyMsg($from, fmt("... not copied to %s", $target));
800 $target = "images/buttons/".basename($from);
801 $zip->addSrcFile($target, $WikiTheme->_path . $from);
803 } elseif (!$silent) {
804 _copyMsg($from, _("... not found"));
808 if (!empty($WikiTheme->dumped_css) and is_array($WikiTheme->dumped_css)) {
809 foreach ($WikiTheme->dumped_css as $css_file) {
810 if (array_key_exists($css_file, $already_images))
812 $already_images[$css_file] = 1;
814 and ($from = $WikiTheme->_findFile(basename($css_file), true))
817 // TODO: fix @import url(main.css);
819 $target = "$directory/" . basename($css_file);
821 copy($WikiTheme->_path . $from, $target);
823 if (copy($WikiTheme->_path . $from, $target)) {
824 _copyMsg($from, fmt("... copied to %s", $target));
826 _copyMsg($from, fmt("... not copied to %s", $target));
830 //$attrib = array('is_ascii' => 0);
831 $target = basename($css_file);
832 $zip->addSrcFile($target, $WikiTheme->_path . $from);
834 } elseif (!$silent) {
835 _copyMsg($from, _("... not found"));
843 if ($WikiTheme->DUMP_MODE == 'PDFHTML') {
844 if (USE_EXTERNAL_HTML2PDF and $outfiles) {
845 $cmd = EXTERNAL_HTML2PDF_PAGELIST.' "'.join('" "', $outfiles).'"';
846 $filename = FilenameForPage($firstpage);
848 $tmpfile = $directory . "/createpdf.bat";
849 $fp = fopen($tmpfile, "wb");
850 fwrite($fp, $cmd . " > $filename.pdf");
853 if (!headers_sent()) {
854 Header('Content-Type: application/pdf');
858 $tmpdir = getUploadFilePath();
859 $s = passthru($cmd . " > $tmpdir/$filename.pdf");
860 $errormsg = "<br />\nGenerated <a href=\"".getUploadDataPath()."$filename.pdf\">Upload:$filename.pdf</a>\n";
865 foreach($outfiles as $f) unlink($f);
868 if (!empty($errormsg)) {
869 $request->discardOutput();
870 $GLOBALS['ErrorManager']->_postponed_errors = array();
874 $ErrorManager->popErrorHandler();
876 $WikiTheme->HTML_DUMP_SUFFIX = '';
877 $WikiTheme->DUMP_MODE = false;
878 $WikiTheme->_MoreAttr['body'] = isset($_bodyAttr) ? $_bodyAttr : '';
881 ////////////////////////////////////////////////////////////////
883 // Functions for restoring.
885 ////////////////////////////////////////////////////////////////
887 function SavePage (&$request, &$pageinfo, $source, $filename)
889 static $overwite_all = false;
890 $pagedata = $pageinfo['pagedata']; // Page level meta-data.
891 $versiondata = $pageinfo['versiondata']; // Revision level meta-data.
893 if (empty($pageinfo['pagename'])) {
894 PrintXML(HTML::p(HTML::strong(_("Empty pagename!"))));
898 if (empty($versiondata['author_id']))
899 $versiondata['author_id'] = $versiondata['author'];
901 // remove invalid backend specific chars. utf8 issues mostly
902 $pagename_check = new WikiPagename($pageinfo['pagename']);
903 if (!$pagename_check->isValid()) {
904 PrintXML(HTML::p(HTML::strong(sprintf(_("'%s': Bad page name"), $pageinfo['pagename']))));
907 $pagename = $pagename_check->getName();
908 $content = $pageinfo['content'];
910 if ($pagename == _("InterWikiMap"))
911 $content = _tryinsertInterWikiMap($content);
913 $dbi =& $request->_dbi;
914 $page = $dbi->getPage($pagename);
916 // Try to merge if updated pgsrc contents are different. This
917 // whole thing is hackish
919 // TODO: try merge unless:
920 // if (current contents = default contents && pgsrc_version >=
921 // pgsrc_version) then just upgrade this pgsrc
922 $needs_merge = false;
926 if ($request->getArg('merge')) {
929 else if ($request->getArg('overwrite')) {
933 $current = $page->getCurrentRevision();
935 $edit = $request->getArg('edit');
937 if (isset($edit['keep_old'])) {
941 elseif (isset($edit['overwrite'])) {
945 elseif ( $current and (! $current->hasDefaultContents())
946 && ($current->getPackedContent() != $content) )
948 include_once('lib/editpage.php');
949 $request->setArg('pagename', $pagename);
950 $v = $current->getVersion();
951 $request->setArg('revision', $current->getVersion());
952 $p = new LoadFileConflictPageEditor($request);
953 $p->_content = $content;
954 $p->_currentVersion = $v - 1;
955 $p->editPage($saveFailed = true);
956 return; //early return
960 foreach ($pagedata as $key => $value) {
962 $page->set($key, $value);
965 $mesg = HTML::p(array('style' => 'text-indent: 3em;'));
967 $mesg->pushContent(' ', fmt("from %s", $source));
970 //FIXME: This should not happen! (empty vdata, corrupt cache or db)
971 $current = $page->getCurrentRevision();
973 if ($current->getVersion() == 0) {
974 $versiondata['author'] = ADMIN_USER;
975 $versiondata['author_id'] = ADMIN_USER;
976 $mesg->pushContent(' - ', _("New page"));
980 if ( (! $current->hasDefaultContents())
981 && ($current->getPackedContent() != $content) ) {
983 $mesg->pushContent(' ',
984 fmt("has edit conflicts - overwriting anyway"));
986 if (substr_count($source, 'pgsrc')) {
987 $versiondata['author'] = ADMIN_USER;
988 // but leave authorid as userid who loaded the file
992 if (isset($edit['keep_old'])) {
993 $mesg->pushContent(' ', fmt("keep old"));
995 $mesg->pushContent(' ', fmt("has edit conflicts - skipped"));
996 $needs_merge = true; // hackish, to display the buttons
1001 else if ($current->getPackedContent() == $content) {
1002 // The page content is the same, we don't need a new revision.
1003 $mesg->pushContent(' ',
1004 fmt("content is identical to current version %d - no new revision created",
1005 $current->getVersion()));
1012 // in case of failures print the culprit:
1013 if (!isa($request,'MockRequest')) {
1014 PrintXML(HTML::p(WikiLink($pagename))); flush();
1016 $new = $page->save($content, WIKIDB_FORCE_CREATE, $versiondata);
1018 $mesg->pushContent(' ', fmt("- saved to database as version %d",
1019 $new->getVersion()));
1023 // hackish, $source contains needed path+filename
1024 $f = str_replace(sprintf(_("MIME file %s"), ''), '', $f);
1025 $f = str_replace(sprintf(_("Serialized file %s"), ''), '', $f);
1026 $f = str_replace(sprintf(_("plain file %s"), ''), '', $f);
1027 //check if uploaded file? they pass just the content, but the file is gone
1030 $meb = Button(array('action' => 'loadfile',
1034 _("PhpWikiAdministration"),
1036 $owb = Button(array('action' => 'loadfile',
1039 _("Restore Anyway"),
1040 _("PhpWikiAdministration"),
1042 $mesg->pushContent(' ', $meb, " ", $owb);
1043 if (!$overwite_all) {
1044 $args = $request->getArgs();
1045 $args['overwrite'] = 1;
1046 $owb = Button($args,
1048 _("PhpWikiAdministration"),
1050 $mesg->pushContent(HTML::span(array('class' => 'hint'), $owb));
1051 $overwite_all = true;
1054 $mesg->pushContent(HTML::em(_(" Sorry, cannot merge.")));
1058 if (!isa($request,'MockRequest')) {
1060 PrintXML(HTML::p(HTML::em(WikiLink($pagename))), $mesg);
1067 // action=revert (by diff)
1068 function RevertPage (&$request)
1070 $mesg = HTML::div();
1071 $pagename = $request->getArg('pagename');
1072 $version = $request->getArg('version');
1073 $dbi =& $request->_dbi;
1074 $page = $dbi->getPage($pagename);
1076 $request->redirect(WikiURL($page,
1077 array('warningmsg' => _('Revert: missing required version argument'))));
1080 $current = $page->getCurrentRevision();
1081 $currversion = $current->getVersion();
1082 if ($currversion == 0) {
1083 $request->redirect(WikiURL($page,
1084 array('errormsg' => _('No revert: no page content'))));
1087 if ($currversion == $version) {
1088 $request->redirect(WikiURL($page,
1089 array('warningmsg' => _('No revert: same version page'))));
1092 if ($request->getArg('cancel')) {
1093 $request->redirect(WikiURL($page,
1094 array('warningmsg' => _('Revert cancelled'))));
1097 if (!$request->getArg('verify')) {
1098 $mesg->pushContent(HTML::p(fmt("Are you sure to revert %s to version $version?", WikiLink($pagename))),
1099 HTML::form(array('action' => $request->getPostURL(),
1100 'method' => 'post'),
1101 HiddenInputs($request->getArgs(), false, array('verify')),
1102 HiddenInputs(array('verify' => 1)),
1103 Button('submit:verify', _("Yes"), 'button'),
1104 HTML::Raw(' '),
1105 Button('submit:cancel', _("Cancel"), 'button'))
1107 $rev = $page->getRevision($version);
1108 $html = HTML(HTML::fieldset($mesg), HTML::hr(), $rev->getTransformedContent());
1109 $template = Template('browse',
1110 array('CONTENT' => $html));
1111 GeneratePage($template, $pagename, $rev);
1112 $request->checkValidators();
1116 $rev = $page->getRevision($version);
1117 $content = $rev->getPackedContent();
1118 $versiondata = $rev->_data;
1119 $versiondata['summary'] = sprintf(_("revert to version %d"), $version);
1120 $versiondata['mtime'] = time();
1121 $new = $page->save($content, $currversion + 1, $versiondata);
1124 $mesg = HTML::span();
1125 $pagelink = WikiLink($pagename);
1126 $mesg->pushContent(fmt("Revert: %s", $pagelink),
1127 fmt("- version %d saved to database as version %d",
1128 $version, $new->getVersion()));
1129 // Force browse of current page version.
1130 $request->setArg('version', false);
1131 $template = Template('savepage', array());
1132 $template->replace('CONTENT', $new->getTransformedContent());
1134 GeneratePage($template, $mesg, $new);
1138 function _tryinsertInterWikiMap($content) {
1140 if (strpos($content, "<verbatim>")) {
1141 //$error_html = " The newly loaded pgsrc already contains a verbatim block.";
1144 if (!$goback && !defined('INTERWIKI_MAP_FILE')) {
1145 $error_html = sprintf(" "._("%s: not defined"), "INTERWIKI_MAP_FILE");
1148 $mapfile = FindFile(INTERWIKI_MAP_FILE,1);
1149 if (!$goback && !file_exists($mapfile)) {
1150 $error_html = sprintf(" "._("%s: file not found"), INTERWIKI_MAP_FILE);
1154 if (!empty($error_html))
1155 trigger_error(_("Default InterWiki map file not loaded.")
1156 . $error_html, E_USER_NOTICE);
1160 // if loading from virgin setup do echo, otherwise trigger_error E_USER_NOTICE
1161 if (!isa($GLOBALS['request'], 'MockRequest'))
1162 echo sprintf(_("Loading InterWikiMap from external file %s."), $mapfile),"<br />";
1164 $fd = fopen ($mapfile, "rb");
1165 $data = fread ($fd, filesize($mapfile));
1167 $content = $content . "\n<verbatim>\n$data</verbatim>\n";
1171 function ParseSerializedPage($text, $default_pagename, $user)
1173 if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
1176 $pagehash = unserialize($text);
1178 // Split up pagehash into four parts:
1181 // page-level meta-data
1182 // revision-level meta-data
1184 if (!defined('FLAG_PAGE_LOCKED'))
1185 define('FLAG_PAGE_LOCKED', 1);
1186 if (!defined('FLAG_PAGE_EXTERNAL'))
1187 define('FLAG_PAGE_EXTERNAL', 1);
1188 $pageinfo = array('pagedata' => array(),
1189 'versiondata' => array());
1191 $pagedata = &$pageinfo['pagedata'];
1192 $versiondata = &$pageinfo['versiondata'];
1194 // Fill in defaults.
1195 if (empty($pagehash['pagename']))
1196 $pagehash['pagename'] = $default_pagename;
1197 if (empty($pagehash['author'])) {
1198 $pagehash['author'] = $user->getId();
1201 foreach ($pagehash as $key => $value) {
1206 $pageinfo[$key] = $value;
1209 $pageinfo[$key] = join("\n", $value);
1212 if (($value & FLAG_PAGE_LOCKED) != 0)
1213 $pagedata['locked'] = 'yes';
1214 if (($value & FLAG_PAGE_EXTERNAL) != 0)
1215 $pagedata['external'] = 'yes';
1219 $pagedata[$key] = $value;
1223 $pagedata['perm'] = ParseMimeifiedPerm($value);
1225 case 'lastmodified':
1226 $versiondata['mtime'] = $value;
1231 $versiondata[$key] = $value;
1235 if (empty($pagehash['charset']))
1236 $pagehash['charset'] = 'utf-8';
1237 // compare to target charset
1238 if (strtolower($pagehash['charset']) != strtolower($GLOBALS['charset'])) {
1239 $pageinfo['content'] = charset_convert($params['charset'], $GLOBALS['charset'], $pageinfo['content']);
1240 $pageinfo['pagename'] = charset_convert($params['charset'], $GLOBALS['charset'], $pageinfo['pagename']);
1245 function SortByPageVersion ($a, $b) {
1246 return $a['version'] - $b['version'];
1250 * Security alert! We should not allow to import config.ini into our wiki (or from a sister wiki?)
1251 * because the sql passwords are in plaintext there. And the webserver must be able to read it.
1252 * Detected by Santtu Jarvi.
1254 function LoadFile (&$request, $filename, $text = false, $mtime = false)
1256 if (preg_match("/config$/", dirname($filename)) // our or other config
1257 and preg_match("/config.*\.ini/", basename($filename))) // backups and other versions also
1259 trigger_error(sprintf("Refused to load %s", $filename), E_USER_WARNING);
1262 if (!is_string($text)) {
1264 $stat = stat($filename);
1266 $text = implode("", file($filename));
1269 if (! $request->getArg('start_debug')) @set_time_limit(30); // Reset watchdog
1270 else @set_time_limit(240);
1272 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
1273 $basename = basename("/dummy/" . $filename);
1276 $mtime = time(); // Last resort.
1278 // DONE: check source - target charset for content and pagename
1279 // but only for pgsrc'ed content, not from the browser.
1281 $default_pagename = rawurldecode($basename);
1282 if ( ($parts = ParseMimeifiedPages($text)) ) {
1283 if (count($parts) > 1)
1284 $overwrite = $request->getArg('overwrite');
1285 usort($parts, 'SortByPageVersion');
1286 foreach ($parts as $pageinfo) {
1288 if (count($parts) > 1)
1289 $request->setArg('overwrite', 1);
1290 SavePage($request, $pageinfo, sprintf(_("MIME file %s"),
1291 $filename), $basename);
1293 if (count($parts) > 1)
1295 $request->setArg('overwrite', $overwrite);
1297 unset($request->_args['overwrite']);
1299 else if ( ($pageinfo = ParseSerializedPage($text, $default_pagename,
1300 $request->getUser())) ) {
1301 SavePage($request, $pageinfo, sprintf(_("Serialized file %s"),
1302 $filename), $basename);
1306 $user = $request->getUser();
1308 $file_charset = 'utf-8';
1309 // compare to target charset
1310 if ($file_charset != strtolower($GLOBALS['charset'])) {
1311 $text = charset_convert($file_charset, $GLOBALS['charset'], $text);
1312 $default_pagename = charset_convert($file_charset, $GLOBALS['charset'], $default_pagename);
1315 // Assume plain text file.
1316 $pageinfo = array('pagename' => $default_pagename,
1317 'pagedata' => array(),
1319 => array('author' => $user->getId()),
1320 'content' => preg_replace('/[ \t\r]*\n/', "\n",
1323 SavePage($request, $pageinfo, sprintf(_("plain file %s"), $filename),
1328 function LoadZip (&$request, $zipfile, $files = false, $exclude = false) {
1329 $zip = new ZipReader($zipfile);
1330 $timeout = (! $request->getArg('start_debug')) ? 20 : 120;
1331 while (list ($fn, $data, $attrib) = $zip->readFile()) {
1332 // FIXME: basename("filewithnoslashes") seems to return
1333 // garbage sometimes.
1334 $fn = basename("/dummy/" . $fn);
1335 if ( ($files && !in_array($fn, $files))
1336 || ($exclude && in_array($fn, $exclude)) ) {
1337 PrintXML(HTML::p(WikiLink($fn)),
1338 HTML::p(_("Skipping")));
1342 longer_timeout($timeout); // longer timeout per page
1343 LoadFile($request, $fn, $data, $attrib['mtime']);
1347 function LoadDir (&$request, $dirname, $files = false, $exclude = false) {
1348 $fileset = new LimitedFileSet($dirname, $files, $exclude);
1350 if (!$files and ($skiplist = $fileset->getSkippedFiles())) {
1351 PrintXML(HTML::p(HTML::strong(_("Skipping"))));
1353 foreach ($skiplist as $file)
1354 $list->pushContent(HTML::li(WikiLink($file)));
1355 PrintXML(HTML::p($list));
1358 // Defer HomePage loading until the end. If anything goes wrong
1359 // the pages can still be loaded again.
1360 $files = $fileset->getFiles();
1361 if (in_array(HOME_PAGE, $files)) {
1362 $files = array_diff($files, array(HOME_PAGE));
1363 $files[] = HOME_PAGE;
1365 $timeout = (! $request->getArg('start_debug')) ? 20 : 120;
1366 foreach ($files as $file) {
1367 longer_timeout($timeout); // longer timeout per page
1368 if (substr($file,-1,1) != '~') // refuse to load backup files
1369 LoadFile($request, "$dirname/$file");
1373 class LimitedFileSet extends FileSet {
1374 function LimitedFileSet($dirname, $_include, $exclude) {
1375 $this->_includefiles = $_include;
1376 $this->_exclude = $exclude;
1377 $this->_skiplist = array();
1378 parent::FileSet($dirname);
1381 function _filenameSelector($fn) {
1382 $incl = &$this->_includefiles;
1383 $excl = &$this->_exclude;
1385 if ( ($incl && !in_array($fn, $incl))
1386 || ($excl && in_array($fn, $excl)) ) {
1387 $this->_skiplist[] = $fn;
1394 function getSkippedFiles () {
1395 return $this->_skiplist;
1399 function IsZipFile ($filename_or_fd)
1401 // See if it looks like zip file
1402 if (is_string($filename_or_fd))
1404 $fd = fopen($filename_or_fd, "rb");
1405 $magic = fread($fd, 4);
1410 $fpos = ftell($filename_or_fd);
1411 $magic = fread($filename_or_fd, 4);
1412 fseek($filename_or_fd, $fpos);
1415 return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
1418 function LoadAny (&$request, $file_or_dir, $files = false, $exclude = false)
1420 // Try urlencoded filename for accented characters.
1421 if (!file_exists($file_or_dir)) {
1422 // Make sure there are slashes first to avoid confusing phps
1423 // with broken dirname or basename functions.
1424 // FIXME: windows uses \ and :
1425 if (is_integer(strpos($file_or_dir, "/"))) {
1426 $newfile = FindFile($file_or_dir, true);
1427 // Panic. urlencoded by the browser (e.g. San%20Diego => San Diego)
1429 $file_or_dir = dirname($file_or_dir) . "/"
1430 . rawurlencode(basename($file_or_dir));
1432 // This is probably just a file.
1433 $file_or_dir = rawurlencode($file_or_dir);
1437 $type = filetype($file_or_dir);
1438 if ($type == 'link') {
1439 // For symbolic links, use stat() to determine
1440 // the type of the underlying file.
1441 list(,,$mode) = stat($file_or_dir);
1442 $type = ($mode >> 12) & 017;
1445 elseif ($type == 004)
1450 $request->finish(fmt("Empty or not existing source. Unable to load: %s", $file_or_dir));
1452 else if ($type == 'dir') {
1453 LoadDir($request, $file_or_dir, $files, $exclude);
1455 else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
1457 $request->finish(fmt("Bad file type: %s", $type));
1459 else if (IsZipFile($file_or_dir)) {
1460 LoadZip($request, $file_or_dir, $files, $exclude);
1462 else /* if (!$files || in_array(basename($file_or_dir), $files)) */
1464 LoadFile($request, $file_or_dir);
1468 function LoadFileOrDir (&$request)
1470 $source = $request->getArg('source');
1471 $finder = new FileFinder;
1472 $source = $finder->slashifyPath($source);
1473 StartLoadDump($request,
1474 sprintf(_("Loading '%s'"), $source));
1475 LoadAny($request, $source);
1476 EndLoadDump($request);
1480 * HomePage was not found so first-time install is supposed to run.
1481 * - import all pgsrc pages.
1482 * - Todo: installer interface to edit config/config.ini settings
1483 * - Todo: ask for existing old index.php to convert to config/config.ini
1484 * - Todo: theme-specific pages:
1485 * blog - HomePage, ADMIN_USER/Blogs
1487 function SetupWiki (&$request)
1489 global $GenericPages, $LANG;
1491 //FIXME: This is a hack (err, "interim solution")
1492 // This is a bogo-bogo-login: Login without
1493 // saving login information in session state.
1494 // This avoids logging in the unsuspecting
1495 // visitor as ADMIN_USER
1497 // This really needs to be cleaned up...
1498 // (I'm working on it.)
1499 $real_user = $request->_user;
1500 if (ENABLE_USER_NEW)
1501 $request->_user = new _BogoUser(ADMIN_USER);
1504 $request->_user = new WikiUser($request, ADMIN_USER, WIKIAUTH_BOGO);
1506 StartLoadDump($request, _("Loading up virgin wiki"));
1508 $pgsrc = FindLocalizedFile(WIKI_PGSRC);
1509 $default_pgsrc = FindFile(DEFAULT_WIKI_PGSRC);
1511 $request->setArg('overwrite', true);
1512 if ($default_pgsrc != $pgsrc) {
1513 LoadAny($request, $default_pgsrc, $GenericPages);
1515 $request->setArg('overwrite', false);
1516 LoadAny($request, $pgsrc);
1517 $dbi =& $request->_dbi;
1519 // Ensure that all mandatory pages are loaded
1520 $finder = new FileFinder;
1523 $mandatory = explode(':','SandBox:Template/Category:Template/Talk:SpecialPages:CategoryCategory:CategoryActionPage:Help/OldTextFormattingRules:Help/TextFormattingRules:PhpWikiAdministration');
1524 } else if (WIKI_NAME == "help") {
1525 $mandatory = explode(':','SandBox:Template/Category:Template/Talk:SpecialPages:CategoryCategory:CategoryActionPage:Help/TextFormattingRules:PhpWikiAdministration');
1527 $mandatory = explode(':','SandBox:Template/UserPage:Template/Category:Template/Talk:SpecialPages:CategoryCategory:CategoryActionPage:TextFormattingRules:PhpWikiAdministration');
1529 foreach (array_merge($mandatory,
1530 $GLOBALS['AllActionPages'],
1531 array(constant('HOME_PAGE'))) as $f)
1533 $page = gettext($f);
1534 $epage = urlencode($page);
1535 if (! $dbi->isWikiPage($page) ) {
1536 // translated version provided?
1537 if ($lf = FindLocalizedFile($pgsrc . $finder->_pathsep . $epage, 1)) {
1538 LoadAny($request, $lf);
1539 } else { // load english version of required action page
1540 LoadAny($request, FindFile(DEFAULT_WIKI_PGSRC . $finder->_pathsep . urlencode($f)));
1544 if (! $dbi->isWikiPage($page)) {
1545 trigger_error(sprintf("Mandatory file %s couldn't be loaded!", $page),
1550 $pagename = _("InterWikiMap");
1551 $map = $dbi->getPage($pagename);
1552 $map->set('locked', true);
1553 PrintXML(HTML::p(HTML::em(WikiLink($pagename)), HTML::strong(" locked")));
1554 EndLoadDump($request);
1557 function LoadPostFile (&$request)
1559 $upload = $request->getUploadedFile('file');
1562 $request->finish(_("No uploaded file to upload?")); // FIXME: more concise message
1564 // Dump http headers.
1565 StartLoadDump($request, sprintf(_("Uploading %s"), $upload->getName()));
1567 $fd = $upload->open();
1569 LoadZip($request, $fd, false, array(_("RecentChanges")));
1571 LoadFile($request, $upload->getName(), $upload->getContents());
1573 EndLoadDump($request);
1579 // c-basic-offset: 4
1580 // c-hanging-comment-ender-p: nil
1581 // indent-tabs-mode: nil