2 rcs_id('$Id: loadsave.php,v 1.2 2001-02-13 05:54:38 dairiki Exp $');
4 require "lib/ziplib.php";
6 function StartLoadDump($title, $html = '')
8 // FIXME: This is a hack
9 echo ereg_replace('</body>.*', '',
10 GeneratePage('MESSAGE', $html, $title, 0));
12 function EndLoadDump()
14 // FIXME: This is a hack
15 echo Element('p', QElement('b', gettext("Complete.")));
16 echo Element('p', "Return to " . LinkExistingWikiWord($GLOBALS['pagename']));
17 echo "</body></html>\n";
21 ////////////////////////////////////////////////////////////////
23 // Functions for dumping.
25 ////////////////////////////////////////////////////////////////
27 function MailifyPage ($pagehash, $oldpagehash = false)
29 global $SERVER_ADMIN, $ArchivePageStore;
31 $from = isset($SERVER_ADMIN) ? $SERVER_ADMIN : 'foo@bar';
33 $head = "From $from " . ctime(time()) . "\r\n";
34 $head .= "Subject: " . rawurlencode($pagehash['pagename']) . "\r\n";
35 $head .= "From: $from (PhpWiki)\r\n";
36 $head .= "Date: " . rfc1123date($pagehash['lastmodified']) . "\r\n";
37 $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n", PHPWIKI_VERSION);
39 if (is_array($oldpagehash))
41 return $head . MimeMultipart(array(MimeifyPage($oldpagehash),
42 MimeifyPage($pagehash)));
45 return $head . MimeifyPage($pagehash);
49 * The main() function which generates a zip archive of a PhpWiki.
51 * If $include_archive is false, only the current version of each page
52 * is included in the zip file; otherwise all archived versions are
55 function MakeWikiZip ($dbi, $include_archive = false)
57 global $WikiPageStore, $ArchivePageStore;
59 $pages = GetAllWikiPageNames($dbi);
60 $zipname = "wiki.zip";
62 if ($include_archive) {
63 $zipname = "wikidb.zip";
66 $zip = new ZipWriter("Created by PhpWiki", $zipname);
68 for (reset($pages); $pagename = current($pages); next($pages))
70 set_time_limit(30); // Reset watchdog.
71 $pagehash = RetrievePage($dbi, $pagename, $WikiPageStore);
73 if (! is_array($pagehash))
77 $oldpagehash = RetrievePage($dbi, $pagename, $ArchivePageStore);
81 $attrib = array('mtime' => $pagehash['lastmodified'],
83 if (($pagehash['flags'] & FLAG_PAGE_LOCKED) != 0)
84 $attrib['write_protected'] = 1;
86 $content = MailifyPage($pagehash, $oldpagehash);
88 $zip->addRegularFile( rawurlencode($pagehash['pagename']),
94 function DumpToDir ($dbi, $directory)
96 global $WikiPageStore;
98 if (empty($directory))
99 ExitWiki(gettext("You must specify a directory to dump to"));
101 // see if we can access the directory the user wants us to use
102 if (! file_exists($directory)) {
103 if (! mkdir($directory, 0755))
104 ExitWiki("Cannot create directory '$directory'<br>\n");
106 $html = "Created directory '$directory' for the page dump...<br>\n";
108 $html = "Using directory '$directory'<br>\n";
111 StartLoadDump("Dumping Pages", $html);
113 $pages = GetAllWikiPagenames($dbi);
115 while (list ($i, $pagename) = each($pages))
117 $enc_name = htmlspecialchars($pagename);
118 $filename = rawurlencode($pagename);
120 echo "<br>$enc_name ... ";
121 if($pagename != $filename)
122 echo "<small>saved as $filename</small> ... ";
124 $page = RetrievePage($dbi, $pagename, $WikiPageStore);
126 //$data = serialize($page);
127 $data = MailifyPage($page);
129 if ( !($fd = fopen("$directory/$filename", "w")) )
130 ExitWiki("<b>couldn't open file '$directory/$filename' for writing</b>\n");
132 $num = fwrite($fd, $data, strlen($data));
133 echo "<small>$num bytes written</small>\n";
136 assert($num == strlen($data));
143 ////////////////////////////////////////////////////////////////
145 // Functions for restoring.
147 ////////////////////////////////////////////////////////////////
149 function SavePage ($dbi, $page, $defaults, $source, $filename)
151 global $WikiPageStore;
153 // Fill in defaults for missing values?
154 // Should we do more sanity checks here?
155 while (list($key, $val) = each($defaults))
156 if (empty($page[$key]))
159 $pagename = $page['pagename'];
161 if (empty($pagename))
163 echo Element('dd'). Element('dt', QElement('b', "Empty pagename!"));
169 $version = $page['version'];
173 $mesg[] = sprintf(gettext("version %s"), $version);
175 $mesg[] = sprintf(gettext("from %s"), $source);
177 if (is_array($current = RetrievePage($dbi, $pagename, $WikiPageStore)))
181 if (arrays_equal($current['content'], $page['content'])
182 && $current['author'] == $page['author']
183 && $current['flags'] == $page['flags'])
185 $mesg[] = sprintf(gettext("is identical to current version %d"),
186 $current['version']);
188 if ( $version <= $current['version'] )
190 $mesg[] = gettext("- skipped");
196 SaveCopyToArchive($dbi, $pagename, $current);
198 if ( $version <= $current['version'] )
199 $page['version'] = $current['version'] + 1;
202 else if ($page['version'] < 1)
203 $page['version'] = 1;
208 InsertPage($dbi, $pagename, $page);
209 UpdateRecentChanges($dbi, $pagename, $isnew);
211 $mesg[] = gettext("- saved");
212 if ($version != $page['version'])
213 $mesg[] = sprintf(gettext("as version %d"), $page['version']);
216 print( Element('dt', LinkExistingWikiWord($pagename))
217 . QElement('dd', join(" ", $mesg))
222 function ParseSerializedPage($text)
224 if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
226 return unserialize($text);
229 function SortByPageVersion ($a, $b) {
230 return $a['version'] - $b['version'];
233 function LoadFile ($dbi, $filename, $text = false, $mtime = false)
235 if (!is_string($text))
238 $stat = stat($filename);
240 $text = implode("", file($filename));
243 set_time_limit(30); // Reset watchdog.
245 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
246 $basename = basename("/dummy/" . $filename);
249 $mtime = time(); // Last resort.
251 $defaults = array('author' => $GLOBALS['user']->id(),
252 'pagename' => rawurldecode($basename),
256 'lastmodified' => $mtime);
258 if ( ($parts = ParseMimeifiedPages($text)) )
260 usort($parts, 'SortByPageVersion');
261 for (reset($parts); $page = current($parts); next($parts))
262 SavePage($dbi, $page, $defaults, "MIME file $filename", $basename);
264 else if ( ($page = ParseSerializedPage($text)) )
266 SavePage($dbi, $page, $defaults, "Serialized file $filename", $basename);
270 // Assume plain text file.
271 $page['content'] = preg_split('/[ \t\r]*\n/', chop($text));
272 SavePage($dbi, $page, $defaults, "plain file $filename", $basename);
276 function LoadZip ($dbi, $zipfile, $files = false, $exclude = false)
278 $zip = new ZipReader($zipfile);
279 while (list ($fn, $data, $attrib) = $zip->readFile())
281 // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
282 $fn = basename("/dummy/" . $fn);
283 if ( ($files && !in_array($fn, $files))
284 || ($exclude && in_array($fn, $exclude)) )
286 print Element('dt', LinkExistingWikiWord($fn)) . QElement('dd', 'Skipping');
290 LoadFile($dbi, $fn, $data, $attrib['mtime']);
294 function LoadDir ($dbi, $dirname, $files = false, $exclude = false)
296 $handle = opendir($dir = $dirname);
297 while ($fn = readdir($handle))
299 if (filetype("$dir/$fn") != 'file')
302 if ( ($files && !in_array($fn, $files))
303 || ($exclude && in_array($fn, $exclude)) )
305 print Element('dt', LinkExistingWikiWord($fn)) . QElement('dd', 'Skipping');
309 LoadFile($dbi, "$dir/$fn");
314 function IsZipFile ($filename_or_fd)
316 // See if it looks like zip file
317 if (is_string($filename_or_fd))
319 $fd = fopen($filename_or_fd, "rb");
320 $magic = fread($fd, 4);
325 $fpos = ftell($filename_or_fd);
326 $magic = fread($filename_or_fd, 4);
327 fseek($filename_or_fd, $fpos);
330 return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
334 function LoadAny ($dbi, $file_or_dir, $files = false, $exclude = false)
336 $type = filetype($file_or_dir);
340 LoadDir($dbi, $file_or_dir, $files, $exclude);
342 else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
344 ExitWiki("Bad file type: $type");
346 else if (IsZipFile($file_or_dir))
348 LoadZip($dbi, $file_or_dir, $files, $exclude);
350 else /* if (!$files || in_array(basename($file_or_dir), $files)) */
352 LoadFile($dbi, $file_or_dir);
356 function LoadFileOrDir ($dbi, $source)
358 StartLoadDump("Loading '$source'");
360 LoadAny($dbi, $source, false, array(gettext('RecentChanges')));
365 function SetupWiki ($dbi)
367 global $GenericPages, $LANG, $user;
369 //FIXME: This is a hack
370 $user->userid = 'The PhpWiki programming team';
372 StartLoadDump('Loading up virgin wiki');
375 LoadAny($dbi, SearchPath(WIKI_PGSRC));
377 LoadAny($dbi, SearchPath(DEFAULT_WIKI_PGSRC), $GenericPages);
383 function LoadPostFile ($dbi, $postname)
385 global $HTTP_POST_FILES;
387 extract($HTTP_POST_FILES[$postname]);
388 fix_magic_quotes_gpc($tmp_name);
389 fix_magic_quotes_gpc($name);
391 if (!is_uploaded_file($tmp_name))
392 ExitWiki('Bad file post'); // Possible malicious attack.
394 // Dump http headers.
395 $fd = fopen($tmp_name, "rb");
396 while ( ($header = fgets($fd, 4096)) )
397 if (trim($header) == '')
400 StartLoadDump("Uploading $name");
404 LoadZip($dbi, $fd, false, array(gettext('RecentChanges')));
406 Loadfile($dbi, $name, fread($fd, MAX_UPLOAD_SIZE));
415 // c-file-style: "ellemtel"