2 rcs_id('$Id: loadsave.php,v 1.26 2002-01-18 05:18:24 carstenklapp 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('strong', _("Complete.")));
18 echo Element('p', sprintf( _("Return to %s"),
19 LinkExistingWikiWord($GLOBALS['pagename']) ) );
20 echo "</body></html>\n";
24 ////////////////////////////////////////////////////////////////
26 // Functions for dumping.
28 ////////////////////////////////////////////////////////////////
30 function MailifyPage ($page, $nversions = 1)
32 global $SERVER_ADMIN, $pagedump_format;
34 $current = $page->getCurrentRevision();
35 $from = isset($SERVER_ADMIN) ? $SERVER_ADMIN : 'foo@bar';
37 if ($pagedump_format == 'quoted-printable') {
38 $head = "From $from " . CTime(time()) . "\r\n";
39 $head .= "Subject: " . rawurlencode($page->getName()) . "\r\n";
40 $head .= "From: $from (PhpWiki)\r\n";
41 $head .= "Date: " . Rfc2822DateTime($current->get('mtime')) . "\r\n";
42 $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n",
45 $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n",
46 PHPWIKI_VERSION."+carsten's-binary-hack");
48 $head .= "X-RCS_ID: $" ."Id" ."$" ."\r\n";
50 $iter = $page->getAllRevisions();
52 while ($revision = $iter->next()) {
53 $parts[] = MimeifyPageRevision($revision);
54 if ($nversions > 0 && count($parts) >= $nversions)
57 if (count($parts) > 1)
58 return $head . MimeMultipart($parts);
60 return $head . $parts[0];
64 * Compute filename to used for storing contents of a wiki page.
66 * Basically we do a rawurlencode() which encodes everything except
67 * ASCII alphanumerics and '.', '-', and '_'.
69 * But we also want to encode leading dots to avoid filenames like
70 * '.', and '..'. (Also, there's no point in generating "hidden" file
71 * names, like '.foo'.)
73 * @param $pagename string Pagename.
74 * @return string Filename for page.
76 function FilenameForPage ($pagename)
78 $enc = rawurlencode($pagename);
79 return preg_replace('/^\./', '%2e', $enc);
83 * The main() function which generates a zip archive of a PhpWiki.
85 * If $include_archive is false, only the current version of each page
86 * is included in the zip file; otherwise all archived versions are
89 function MakeWikiZip ($dbi, $request)
91 if ($request->getArg('include') == 'all') {
92 $zipname = "wikidb.zip";
93 $include_archive = true;
96 $zipname = "wiki.zip";
97 $include_archive = false;
102 $zip = new ZipWriter("Created by PhpWiki", $zipname);
104 $pages = $dbi->getAllPages();
105 while ($page = $pages->next()) {
106 set_time_limit(30); // Reset watchdog.
108 $current = $page->getCurrentRevision();
109 if ($current->getVersion() == 0)
113 $attrib = array('mtime' => $current->get('mtime'),
115 if ($page->get('locked'))
116 $attrib['write_protected'] = 1;
118 if ($include_archive)
119 $content = MailifyPage($page, 0);
121 $content = MailifyPage($page);
123 $zip->addRegularFile( FilenameForPage($page->getName()),
129 function DumpToDir ($dbi, $request)
131 global $pagedump_format;
132 $directory = $request->getArg('directory');
133 if (empty($directory))
134 ExitWiki(_("You must specify a directory to dump to"));
136 // see if we can access the directory the user wants us to use
137 if (! file_exists($directory)) {
138 if (! mkdir($directory, 0755))
139 ExitWiki( sprintf(_("Cannot create directory '%s'"),
140 $directory) . "<br />\n");
142 $html = sprintf(_("Created directory '%s' for the page dump..."),
143 $directory) . "<br />\n";
145 $html = sprintf(_("Using directory '%s'"),$directory) . "<br />\n";
148 $html .= "MIME " . $pagedump_format . "<br />\n";
149 StartLoadDump( _("Dumping Pages"), $html);
151 $pages = $dbi->getAllPages();
153 while ($page = $pages->next()) {
155 $enc_name = htmlspecialchars($page->getName());
156 $filename = FilenameForPage($page->getName());
158 echo "<br />$enc_name ... ";
159 if($page->getName() != $filename)
160 echo "<small>" . sprintf(_("saved as %s"),$filename)
163 $data = MailifyPage($page);
165 if ( !($fd = fopen("$directory/$filename", "w")) )
166 ExitWiki("<strong>" . sprintf(_("couldn't open file '%s' for writing"),
167 "$directory/$filename") . "</strong>\n");
169 $num = fwrite($fd, $data, strlen($data));
170 echo "<small>" . sprintf(_("%s bytes written"),$num) . "</small>\n";
173 assert($num == strlen($data));
180 ////////////////////////////////////////////////////////////////
182 // Functions for restoring.
184 ////////////////////////////////////////////////////////////////
186 function SavePage ($dbi, $pageinfo, $source, $filename)
188 $pagedata = $pageinfo['pagedata']; // Page level meta-data.
189 $versiondata = $pageinfo['versiondata']; // Revision level meta-data.
191 if (empty($pageinfo['pagename'])) {
192 echo Element('dd'). Element('dt', QElement('strong',
193 _("Empty pagename!") ));
197 if (empty($versiondata['author_id']))
198 $versiondata['author_id'] = $versiondata['author'];
200 $pagename = $pageinfo['pagename'];
201 $content = $pageinfo['content'];
203 $page = $dbi->getPage($pagename);
205 foreach ($pagedata as $key => $value) {
207 $page->set($key, $value);
213 $mesg[] = sprintf(_("from %s"), $source);
215 $current = $page->getCurrentRevision();
216 if ($current->getVersion() == 0) {
217 $mesg[] = _("new page");
221 if ($current->getPackedContent() == $content
222 && $current->get('author') == $versiondata['author']) {
223 $mesg[] = sprintf(_("is identical to current version %d"),
224 $current->getVersion());
225 $mesg[] = _("- skipped");
232 $new = $page->createRevision(WIKIDB_FORCE_CREATE, $content,
234 ExtractWikiPageLinks($content));
236 $mesg[] = sprintf(_("- saved to database as version %d"),
240 print( Element('dt', LinkExistingWikiWord($pagename))
241 . QElement('dd', join(" ", $mesg))
246 function ParseSerializedPage($text, $default_pagename)
248 if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
251 $pagehash = unserialize($text);
253 // Split up pagehash into four parts:
256 // page-level meta-data
257 // revision-level meta-data
259 if (!defined('FLAG_PAGE_LOCKED'))
260 define('FLAG_PAGE_LOCKED', 1);
261 $pageinfo = array('pagedata' => array(),
262 'versiondata' => array());
264 $pagedata = &$pageinfo['pagedata'];
265 $versiondata = &$pageinfo['versiondata'];
268 if (empty($pagehash['pagename']))
269 $pagehash['pagename'] = $default_pagename;
270 if (empty($pagehash['author']))
271 $pagehash['author'] = $GLOBALS['user']->id();
274 foreach ($pagehash as $key => $value) {
278 $pageinfo[$key] = $value;
281 $pageinfo[$key] = join("\n", $value);
283 if (($value & FLAG_PAGE_LOCKED) != 0)
284 $pagedata['locked'] = 'yes';
287 $pagedata[$key] = $value;
290 $versiondata['mtime'] = $value;
293 $versiondata[$key] = $value;
300 function SortByPageVersion ($a, $b) {
301 return $a['version'] - $b['version'];
304 function LoadFile ($dbi, $filename, $text = false, $mtime = false)
306 if (!is_string($text)) {
308 $stat = stat($filename);
310 $text = implode("", file($filename));
313 set_time_limit(30); // Reset watchdog.
315 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
316 $basename = basename("/dummy/" . $filename);
319 $mtime = time(); // Last resort.
321 $defaults = array('author' => $GLOBALS['user']->id(),
322 'pagename' => rawurldecode($basename));
324 $default_pagename = rawurldecode($basename);
326 if ( ($parts = ParseMimeifiedPages($text)) ) {
327 usort($parts, 'SortByPageVersion');
328 foreach ($parts as $pageinfo)
329 SavePage($dbi, $pageinfo, sprintf(_("MIME file %s"),$filename),
332 else if ( ($pageinfo = ParseSerializedPage($text, $default_pagename)) ) {
333 SavePage($dbi, $pageinfo, sprintf(_("Serialized file %s"),$filename),
337 // Assume plain text file.
338 $pageinfo = array('pagename' => $default_pagename,
339 'pagedata' => array(),
341 => array('author' => $GLOBALS['user']->id()),
342 'content' => preg_replace('/[ \t\r]*\n/', "\n",
345 SavePage($dbi, $pageinfo, sprintf(_("plain file %s"),$filename),
350 function LoadZip ($dbi, $zipfile, $files = false, $exclude = false)
352 $zip = new ZipReader($zipfile);
353 while (list ($fn, $data, $attrib) = $zip->readFile())
355 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
356 $fn = basename("/dummy/" . $fn);
357 if ( ($files && !in_array($fn, $files))
358 || ($exclude && in_array($fn, $exclude)) )
360 print Element('dt', LinkExistingWikiWord($fn))
361 . QElement('dd', _("Skipping"));
365 LoadFile($dbi, $fn, $data, $attrib['mtime']);
369 function LoadDir ($dbi, $dirname, $files = false, $exclude = false)
371 $handle = opendir($dir = $dirname);
372 while ($fn = readdir($handle))
374 if ($fn[0] == '.' || filetype("$dir/$fn") != 'file')
377 if ( ($files && !in_array($fn, $files))
378 || ($exclude && in_array($fn, $exclude)) )
380 print Element('dt', LinkExistingWikiWord($fn))
381 . QElement('dd', _("Skipping"));
385 LoadFile($dbi, "$dir/$fn");
390 function IsZipFile ($filename_or_fd)
392 // See if it looks like zip file
393 if (is_string($filename_or_fd))
395 $fd = fopen($filename_or_fd, "rb");
396 $magic = fread($fd, 4);
401 $fpos = ftell($filename_or_fd);
402 $magic = fread($filename_or_fd, 4);
403 fseek($filename_or_fd, $fpos);
406 return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
410 function LoadAny ($dbi, $file_or_dir, $files = false, $exclude = false)
412 // FIXME: This is a partial workaround for sf bug #501145
413 if (substr_count($file_or_dir,"/") < 1) {
414 $type = filetype(rawurlencode($file_or_dir));
416 $type = filetype($file_or_dir);
419 if ($type == 'dir') {
420 LoadDir($dbi, $file_or_dir, $files, $exclude);
422 else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
424 ExitWiki( sprintf(_("Bad file type: %s"),$type) );
426 else if (IsZipFile($file_or_dir)) {
427 LoadZip($dbi, $file_or_dir, $files, $exclude);
429 else /* if (!$files || in_array(basename($file_or_dir), $files)) */
431 LoadFile($dbi, $file_or_dir);
435 function LoadFileOrDir ($dbi, $request)
437 $source = $request->getArg('source');
438 StartLoadDump( sprintf(_("Loading '%s'"),$source) );
440 LoadAny($dbi, $source/*, false, array(gettext("RecentChanges"))*/);
445 function SetupWiki ($dbi)
447 global $GenericPages, $LANG, $user;
449 //FIXME: This is a hack
450 $user->userid = _("The PhpWiki programming team");
452 StartLoadDump(_("Loading up virgin wiki"));
455 LoadAny($dbi, FindLocalizedFile(WIKI_PGSRC)/*, false, $ignore*/);
457 LoadAny($dbi, FindFile(DEFAULT_WIKI_PGSRC),
458 $GenericPages/*, $ignore*/);
464 function LoadPostFile ($dbi, $request)
466 $upload = $request->getUploadedFile('file');
469 // FIXME: better message?
470 ExitWiki(_("No uploaded file to upload?"));
472 // Dump http headers.
473 StartLoadDump( sprintf(_("Uploading %s"),$upload->getName()) );
476 $fd = $upload->open();
478 LoadZip($dbi, $fd, false, array(_("RecentChanges")));
480 Loadfile($dbi, $upload->getName(), $upload->getContents());
491 // c-hanging-comment-ender-p: nil
492 // indent-tabs-mode: nil