2 rcs_id('$Id: loadsave.php,v 1.11 2001-11-14 17:43:50 dairiki Exp $');
3 require_once("lib/ziplib.php");
4 require_once("lib/Template.php");
6 function StartLoadDump($title, $html = '')
8 // FIXME: This is a hack
9 echo ereg_replace('</body>.*', '',
10 GeneratePage('MESSAGE', $html, $title, 0));
13 function EndLoadDump()
15 // FIXME: This is a hack
17 echo Element('p', QElement('b', gettext("Complete.")));
18 echo Element('p', "Return to " . LinkExistingWikiWord($GLOBALS['pagename']));
19 echo "</body></html>\n";
23 ////////////////////////////////////////////////////////////////
25 // Functions for dumping.
27 ////////////////////////////////////////////////////////////////
29 function MailifyPage ($page, $nversions = 1)
33 $current = $page->getCurrentRevision();
34 $from = isset($SERVER_ADMIN) ? $SERVER_ADMIN : 'foo@bar';
36 $head = "From $from " . ctime(time()) . "\r\n";
37 $head .= "Subject: " . rawurlencode($page->getName()) . "\r\n";
38 $head .= "From: $from (PhpWiki)\r\n";
39 $head .= "Date: " . rfc1123date($current->get('mtime')) . "\r\n";
40 $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n", PHPWIKI_VERSION);
42 $iter = $page->getAllRevisions();
44 while ($revision = $iter->next()) {
45 $parts[] = MimeifyPageRevision($revision);
46 if ($nversions > 0 && count($parts) >= $nversions)
49 if (count($parts) > 1)
50 return $head . MimeMultipart($parts);
52 return $head . $parts[0];
56 * Compute filename to used for storing contents of a wiki page.
58 * Basically we do a rawurlencode() which encodes everything
59 * except ASCII alphanumerics and '.', '-', and '_'.
61 * But we also want to encode leading dots to avoid filenames
62 * like '.', and '..'. (Also, there's no point in generating
63 * "hidden" file names, like '.foo'.)
65 * @param $pagename string Pagename.
66 * @return string Filename for page.
68 function FilenameForPage ($pagename)
70 $enc = rawurlencode($pagename);
71 return preg_replace('/^\./', '%2e', $enc);
75 * The main() function which generates a zip archive of a PhpWiki.
77 * If $include_archive is false, only the current version of each page
78 * is included in the zip file; otherwise all archived versions are
81 function MakeWikiZip ($dbi, $request)
83 if ($request->getArg('include') == 'all') {
84 $zipname = "wikidb.zip";
85 $include_archive = true;
88 $zipname = "wiki.zip";
89 $include_archive = false;
94 $zip = new ZipWriter("Created by PhpWiki", $zipname);
96 $pages = $dbi->getAllPages();
97 while ($page = $pages->next()) {
98 set_time_limit(30); // Reset watchdog.
100 $current = $page->getCurrentRevision();
101 if ($current->getVersion() == 0)
105 $attrib = array('mtime' => $current->get('mtime'),
107 if ($page->get('locked'))
108 $attrib['write_protected'] = 1;
110 if ($include_archive)
111 $content = MailifyPage($page, 0);
113 $content = MailifyPage($page);
115 $zip->addRegularFile( FilenameForPage($page->getName()),
121 function DumpToDir ($dbi, $request)
123 $directory = $request->getArg('directory');
124 if (empty($directory))
125 ExitWiki(gettext("You must specify a directory to dump to"));
127 // see if we can access the directory the user wants us to use
128 if (! file_exists($directory)) {
129 if (! mkdir($directory, 0755))
130 ExitWiki("Cannot create directory '$directory'<br>\n");
132 $html = "Created directory '$directory' for the page dump...<br>\n";
134 $html = "Using directory '$directory'<br>\n";
137 StartLoadDump("Dumping Pages", $html);
139 $pages = $dbi->getAllPages();
141 while ($page = $pages->next()) {
143 $enc_name = htmlspecialchars($page->getName());
144 $filename = FilenameForPage($page->getName());
146 echo "<br>$enc_name ... ";
147 if($pagename != $filename)
148 echo "<small>saved as $filename</small> ... ";
150 $data = MailifyPage($page);
152 if ( !($fd = fopen("$directory/$filename", "w")) )
153 ExitWiki("<b>couldn't open file '$directory/$filename' for writing</b>\n");
155 $num = fwrite($fd, $data, strlen($data));
156 echo "<small>$num bytes written</small>\n";
159 assert($num == strlen($data));
166 ////////////////////////////////////////////////////////////////
168 // Functions for restoring.
170 ////////////////////////////////////////////////////////////////
172 function SavePage ($dbi, $pageinfo, $source, $filename)
174 $pagedata = $pageinfo['pagedata']; // Page level meta-data.
175 $versiondata = $pageinfo['versiondata']; // Revision level meta-data.
177 if (empty($pageinfo['pagename'])) {
178 echo Element('dd'). Element('dt', QElement('b', "Empty pagename!"));
182 if (empty($versiondata['author_id']))
183 $versiondata['author_id'] = $versiondata['author'];
185 $pagename = $pageinfo['pagename'];
186 $content = $pageinfo['content'];
188 $page = $dbi->getPage($pagename);
190 foreach ($pagedata as $key => $value) {
192 $page->set($key, $value);
198 $mesg[] = sprintf(gettext("from %s"), $source);
200 $current = $page->getCurrentRevision();
201 if ($current->getVersion() == 0) {
202 $mesg[] = gettext("new page");
206 if ($current->getPackedContent() == $content
207 && $current->get('author') == $versiondata['author']) {
208 $mesg[] = sprintf(gettext("is identical to current version %d"),
209 $current->getVersion());
210 $mesg[] = gettext("- skipped");
217 $new = $page->createRevision(WIKIDB_FORCE_CREATE, $content,
219 ExtractWikiPageLinks($content));
221 $mesg[] = gettext("- saved");
222 $mesg[] = sprintf(gettext("- saved as version %d"), $new->getVersion());
225 print( Element('dt', LinkExistingWikiWord($pagename))
226 . QElement('dd', join(" ", $mesg))
231 function ParseSerializedPage($text, $default_pagename)
233 if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
236 $pagehash = unserialize($text);
238 // Split up pagehash into four parts:
241 // page-level meta-data
242 // revision-level meta-data
244 if (!defined('FLAG_PAGE_LOCKED'))
245 define('FLAG_PAGE_LOCKED', 1);
246 $pageinfo = array('pagedata' => array(),
247 'versiondata' => array());
249 $pagedata = &$pageinfo['pagedata'];
250 $versiondata = &$pageinfo['versiondata'];
253 if (empty($pagehash['pagename']))
254 $pagehash['pagename'] = $default_pagename;
255 if (empty($pagehash['author']))
256 $pagehash['author'] = $GLOBALS['user']->id();
259 foreach ($pagehash as $key => $value) {
263 $pageinfo[$key] = $value;
266 $pageinfo[$key] = join("\n", $value);
268 if (($value & FLAG_PAGE_LOCKED) != 0)
269 $pagedata['locked'] = 'yes';
272 $pagedata[$key] = $value;
275 $versiondata['mtime'] = $value;
278 $versiondata[$key] = $value;
285 function SortByPageVersion ($a, $b) {
286 return $a['version'] - $b['version'];
289 function LoadFile ($dbi, $filename, $text = false, $mtime = false)
291 if (!is_string($text)) {
293 $stat = stat($filename);
295 $text = implode("", file($filename));
298 set_time_limit(30); // Reset watchdog.
300 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
301 $basename = basename("/dummy/" . $filename);
304 $mtime = time(); // Last resort.
306 $defaults = array('author' => $GLOBALS['user']->id(),
307 'pagename' => rawurldecode($basename));
309 $default_pagename = rawurldecode($basename);
311 if ( ($parts = ParseMimeifiedPages($text)) ) {
312 usort($parts, 'SortByPageVersion');
313 foreach ($parts as $pageinfo)
314 SavePage($dbi, $pageinfo, "MIME file $filename", $basename);
316 else if ( ($pageinfo = ParseSerializedPage($text, $default_pagename)) ) {
317 SavePage($dbi, $pageinfo, "Serialized file $filename", $basename);
320 // Assume plain text file.
321 $pageinfo = array('pagename' => $default_pagename,
322 'pagedata' => array(),
324 => array('author' => $GLOBALS['user']->id()),
326 => preg_replace('/[ \t\r]*\n/', "\n", chop($text))
328 SavePage($dbi, $pageinfo, "plain file $filename", $basename);
332 function LoadZip ($dbi, $zipfile, $files = false, $exclude = false)
334 $zip = new ZipReader($zipfile);
335 while (list ($fn, $data, $attrib) = $zip->readFile())
337 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
338 $fn = basename("/dummy/" . $fn);
339 if ( ($files && !in_array($fn, $files))
340 || ($exclude && in_array($fn, $exclude)) )
342 print Element('dt', LinkExistingWikiWord($fn)) . QElement('dd', 'Skipping');
346 LoadFile($dbi, $fn, $data, $attrib['mtime']);
350 function LoadDir ($dbi, $dirname, $files = false, $exclude = false)
352 $handle = opendir($dir = $dirname);
353 while ($fn = readdir($handle))
355 if ($fn[0] == '.' || filetype("$dir/$fn") != 'file')
358 if ( ($files && !in_array($fn, $files))
359 || ($exclude && in_array($fn, $exclude)) )
361 print Element('dt', LinkExistingWikiWord($fn)) . QElement('dd', 'Skipping');
365 LoadFile($dbi, "$dir/$fn");
370 function IsZipFile ($filename_or_fd)
372 // See if it looks like zip file
373 if (is_string($filename_or_fd))
375 $fd = fopen($filename_or_fd, "rb");
376 $magic = fread($fd, 4);
381 $fpos = ftell($filename_or_fd);
382 $magic = fread($filename_or_fd, 4);
383 fseek($filename_or_fd, $fpos);
386 return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
390 function LoadAny ($dbi, $file_or_dir, $files = false, $exclude = false)
392 $type = filetype($file_or_dir);
396 LoadDir($dbi, $file_or_dir, $files, $exclude);
398 else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
400 ExitWiki("Bad file type: $type");
402 else if (IsZipFile($file_or_dir))
404 LoadZip($dbi, $file_or_dir, $files, $exclude);
406 else /* if (!$files || in_array(basename($file_or_dir), $files)) */
408 LoadFile($dbi, $file_or_dir);
412 function LoadFileOrDir ($dbi, $request)
414 $source = $request->getArg('source');
415 StartLoadDump("Loading '$source'");
417 LoadAny($dbi, $source/*, false, array(gettext('RecentChanges'))*/);
422 function SetupWiki ($dbi)
424 global $GenericPages, $LANG, $user;
426 //FIXME: This is a hack
427 $user->userid = 'The PhpWiki programming team';
429 StartLoadDump('Loading up virgin wiki');
432 LoadAny($dbi, FindLocalizedFile(WIKI_PGSRC)/*, false, $ignore*/);
434 LoadAny($dbi, FindFile(DEFAULT_WIKI_PGSRC), $GenericPages/*, $ignore*/);
440 function LoadPostFile ($dbi, $request)
442 $upload = $request->getUploadedFile('file');
445 ExitWiki('No uploaded file to upload?');
447 // Dump http headers.
448 StartLoadDump("Uploading " . $upload->getName());
451 $fd = $upload->open();
453 LoadZip($dbi, $fd, false, array(gettext('RecentChanges')));
455 Loadfile($dbi, $upload->getName(), $upload->getContents());
466 // c-hanging-comment-ender-p: nil
467 // indent-tabs-mode: nil