]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/loadsave.php
Delete ctime() and rfc1123date() from lib/ziplib.php in favor of
[SourceForge/phpwiki.git] / lib / loadsave.php
1 <?php
2 rcs_id('$Id: loadsave.php,v 1.14 2001-12-11 18:21:38 dairiki Exp $');
3 require_once("lib/ziplib.php");
4 require_once("lib/Template.php");
5
6 function StartLoadDump($title, $html = '')
7 {
8    // FIXME: This is a hack
9    echo ereg_replace('</body>.*', '',
10                      GeneratePage('MESSAGE', $html, $title, 0));
11 }
12
13 function EndLoadDump()
14 {
15    // FIXME: This is a hack
16     
17    echo Element('p', QElement('b', gettext("Complete.")));
18    echo Element('p', "Return to " . LinkExistingWikiWord($GLOBALS['pagename']));
19    echo "</body></html>\n";
20 }
21
22    
23 ////////////////////////////////////////////////////////////////
24 //
25 //  Functions for dumping.
26 //
27 ////////////////////////////////////////////////////////////////
28
29 function MailifyPage ($page, $nversions = 1)
30 {
31    global $SERVER_ADMIN;
32
33    $current = $page->getCurrentRevision();
34    $from = isset($SERVER_ADMIN) ? $SERVER_ADMIN : 'foo@bar';
35   
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: " . Rfc2822DateTime($current->get('mtime')) . "\r\n";
40    $head .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n", PHPWIKI_VERSION);
41
42    $iter = $page->getAllRevisions();
43    $parts = array();
44    while ($revision = $iter->next()) {
45        $parts[] = MimeifyPageRevision($revision);
46        if ($nversions > 0 && count($parts) >= $nversions)
47            break;
48    }
49    if (count($parts) > 1)
50        return $head . MimeMultipart($parts);
51    assert($parts);
52    return $head . $parts[0];
53 }
54
55 /***
56  * Compute filename to used for storing contents of a wiki page.
57  *
58  * Basically we do a rawurlencode() which encodes everything
59  * except ASCII alphanumerics and '.', '-', and '_'.
60  *
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'.)
64  *
65  * @param $pagename string Pagename.
66  * @return string Filename for page.
67  */
68 function FilenameForPage ($pagename)
69 {
70     $enc = rawurlencode($pagename);
71     return preg_replace('/^\./', '%2e', $enc);
72 }
73
74 /**
75  * The main() function which generates a zip archive of a PhpWiki.
76  *
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
79  * included as well.
80  */
81 function MakeWikiZip ($dbi, $request)
82 {
83     if ($request->getArg('include') == 'all') {
84         $zipname = "wikidb.zip";
85         $include_archive = true;
86     }
87     else {
88         $zipname = "wiki.zip";
89         $include_archive = false;
90     }
91     
92         
93
94     $zip = new ZipWriter("Created by PhpWiki", $zipname);
95
96     $pages = $dbi->getAllPages();
97     while ($page = $pages->next()) {
98         set_time_limit(30);     // Reset watchdog.
99
100         $current = $page->getCurrentRevision();
101         if ($current->getVersion() == 0)
102             continue;
103         
104
105         $attrib = array('mtime' => $current->get('mtime'),
106                         'is_ascii' => 1);
107         if ($page->get('locked'))
108             $attrib['write_protected'] = 1;
109
110         if ($include_archive)
111             $content = MailifyPage($page, 0);
112         else
113             $content = MailifyPage($page);
114                      
115         $zip->addRegularFile( FilenameForPage($page->getName()),
116                               $content, $attrib);
117     }
118     $zip->finish();
119 }
120
121 function DumpToDir ($dbi, $request) 
122 {
123     $directory = $request->getArg('directory');
124     if (empty($directory))
125         ExitWiki(gettext("You must specify a directory to dump to"));
126    
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");
131         else
132             $html = "Created directory '$directory' for the page dump...<br>\n";
133     } else {
134         $html = "Using directory '$directory'<br>\n";
135     }
136
137     StartLoadDump("Dumping Pages", $html);
138    
139     $pages = $dbi->getAllPages();
140     
141     while ($page = $pages->next()) {
142         
143         $enc_name = htmlspecialchars($page->getName());
144         $filename = FilenameForPage($page->getName());
145
146         echo "<br>$enc_name ... ";
147         if($pagename != $filename)
148             echo "<small>saved as $filename</small> ... ";
149
150         $data = MailifyPage($page);
151       
152         if ( !($fd = fopen("$directory/$filename", "w")) )
153             ExitWiki("<b>couldn't open file '$directory/$filename' for writing</b>\n");
154       
155         $num = fwrite($fd, $data, strlen($data));
156         echo "<small>$num bytes written</small>\n";
157         flush();
158       
159         assert($num == strlen($data));
160         fclose($fd);
161     }
162
163     EndLoadDump();
164 }
165
166 ////////////////////////////////////////////////////////////////
167 //
168 //  Functions for restoring.
169 //
170 ////////////////////////////////////////////////////////////////
171
172 function SavePage ($dbi, $pageinfo, $source, $filename)
173 {
174     $pagedata = $pageinfo['pagedata']; // Page level meta-data.
175     $versiondata = $pageinfo['versiondata']; // Revision level meta-data.
176
177     if (empty($pageinfo['pagename'])) {
178         echo Element('dd'). Element('dt', QElement('b', "Empty pagename!"));
179         return;
180     }
181
182     if (empty($versiondata['author_id']))
183         $versiondata['author_id'] = $versiondata['author'];
184     
185     $pagename = $pageinfo['pagename'];
186     $content = $pageinfo['content'];
187
188     $page = $dbi->getPage($pagename);
189
190     foreach ($pagedata as $key => $value) {
191         if (!empty($value))
192             $page->set($key, $value);
193     }
194     
195     $mesg = array();
196     $skip = false;
197     if ($source)
198         $mesg[] = sprintf(gettext("from %s"), $source);
199
200     $current = $page->getCurrentRevision();
201     if ($current->getVersion() == 0) {
202         $mesg[] = gettext("new page");
203         $isnew = true;
204     }
205     else {
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");
211             $skip = true;
212         }
213         $isnew = false;
214     }
215
216     if (! $skip) {
217         $new = $page->createRevision(WIKIDB_FORCE_CREATE, $content,
218                                      $versiondata,
219                                      ExtractWikiPageLinks($content));
220
221         $mesg[] = sprintf(gettext("- saved as version %d"), $new->getVersion());
222     }
223    
224     print( Element('dt', LinkExistingWikiWord($pagename))
225            . QElement('dd', join(" ", $mesg))
226            . "\n" );
227     flush();
228 }
229
230 function ParseSerializedPage($text, $default_pagename)
231 {
232     if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
233         return false;
234
235     $pagehash = unserialize($text);
236
237     // Split up pagehash into four parts:
238     //   pagename
239     //   content
240     //   page-level meta-data
241     //   revision-level meta-data
242     
243     if (!defined('FLAG_PAGE_LOCKED'))
244         define('FLAG_PAGE_LOCKED', 1);
245     $pageinfo = array('pagedata' => array(),
246                       'versiondata' => array());
247
248     $pagedata = &$pageinfo['pagedata'];
249     $versiondata = &$pageinfo['versiondata'];
250
251     // Fill in defaults.
252     if (empty($pagehash['pagename']))
253         $pagehash['pagename'] = $default_pagename;
254     if (empty($pagehash['author']))
255         $pagehash['author'] = $GLOBALS['user']->id();
256     
257
258     foreach ($pagehash as $key => $value) {
259         switch($key) {
260         case 'pagename':
261         case 'version':
262             $pageinfo[$key] = $value;
263             break;
264         case 'content':
265             $pageinfo[$key] = join("\n", $value);
266         case 'flags':
267             if (($value & FLAG_PAGE_LOCKED) != 0)
268                 $pagedata['locked'] = 'yes';
269             break;
270         case 'created':
271             $pagedata[$key] = $value;
272             break;
273         case 'lastmodified':
274             $versiondata['mtime'] = $value;
275             break;
276         case 'author':
277             $versiondata[$key] = $value;
278             break;
279         }
280     }
281     return $pageinfo;
282 }
283  
284 function SortByPageVersion ($a, $b) {
285    return $a['version'] - $b['version'];
286 }
287
288 function LoadFile ($dbi, $filename, $text = false, $mtime = false)
289 {
290     if (!is_string($text)) {
291         // Read the file.
292         $stat = stat($filename);
293         $mtime = $stat[9];
294         $text = implode("", file($filename));
295     }
296    
297     set_time_limit(30); // Reset watchdog.
298
299     // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
300     $basename = basename("/dummy/" . $filename);
301    
302     if (!$mtime)
303         $mtime = time();        // Last resort.
304
305     $defaults = array('author' => $GLOBALS['user']->id(),
306                       'pagename' => rawurldecode($basename));
307
308     $default_pagename = rawurldecode($basename);
309     
310     if ( ($parts = ParseMimeifiedPages($text)) ) {
311         usort($parts, 'SortByPageVersion');
312         foreach ($parts as $pageinfo)
313             SavePage($dbi, $pageinfo, "MIME file $filename", $basename);
314     }
315     else if ( ($pageinfo = ParseSerializedPage($text, $default_pagename)) ) {
316         SavePage($dbi, $pageinfo, "Serialized file $filename", $basename);
317     }
318     else {
319         // Assume plain text file.
320         $pageinfo = array('pagename' => $default_pagename,
321                           'pagedata' => array(),
322                           'versiondata'
323                           => array('author' => $GLOBALS['user']->id()),
324                           'content'
325                           => preg_replace('/[ \t\r]*\n/', "\n", chop($text))
326                           );
327         SavePage($dbi, $pageinfo, "plain file $filename", $basename);
328     }
329 }
330
331 function LoadZip ($dbi, $zipfile, $files = false, $exclude = false)
332 {
333    $zip = new ZipReader($zipfile);
334    while (list ($fn, $data, $attrib) = $zip->readFile())
335    {
336       // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
337       $fn = basename("/dummy/" . $fn);
338       if ( ($files && !in_array($fn, $files))
339            || ($exclude && in_array($fn, $exclude)) )
340       {
341          print Element('dt', LinkExistingWikiWord($fn)) . QElement('dd', 'Skipping');
342          continue;
343       }
344
345       LoadFile($dbi, $fn, $data, $attrib['mtime']);
346    }
347 }
348
349 function LoadDir ($dbi, $dirname, $files = false, $exclude = false)
350 {
351    $handle = opendir($dir = $dirname);
352    while ($fn = readdir($handle))
353    {
354       if ($fn[0] == '.' || filetype("$dir/$fn") != 'file')
355          continue;
356
357       if ( ($files && !in_array($fn, $files))
358            || ($exclude && in_array($fn, $exclude)) )
359       {
360          print Element('dt', LinkExistingWikiWord($fn)) . QElement('dd', 'Skipping');
361          continue;
362       }
363       
364       LoadFile($dbi, "$dir/$fn");
365    }
366    closedir($handle);
367 }
368
369 function IsZipFile ($filename_or_fd)
370 {
371    // See if it looks like zip file
372    if (is_string($filename_or_fd))
373    {
374       $fd = fopen($filename_or_fd, "rb");
375       $magic = fread($fd, 4);
376       fclose($fd);
377    }
378    else
379    {
380       $fpos = ftell($filename_or_fd);
381       $magic = fread($filename_or_fd, 4);
382       fseek($filename_or_fd, $fpos);
383    }
384    
385    return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
386 }
387
388    
389 function LoadAny ($dbi, $file_or_dir, $files = false, $exclude = false)
390 {
391    $type = filetype($file_or_dir);
392
393    if ($type == 'dir')
394    {
395       LoadDir($dbi, $file_or_dir, $files, $exclude);
396    }
397    else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
398    {
399       ExitWiki("Bad file type: $type");
400    }
401    else if (IsZipFile($file_or_dir))
402    {
403       LoadZip($dbi, $file_or_dir, $files, $exclude);
404    }
405    else /* if (!$files || in_array(basename($file_or_dir), $files)) */
406    {
407       LoadFile($dbi, $file_or_dir);
408    }
409 }
410
411 function LoadFileOrDir ($dbi, $request)
412 {
413    $source = $request->getArg('source');
414    StartLoadDump("Loading '$source'");
415    echo "<dl>\n";
416    LoadAny($dbi, $source/*, false, array(gettext('RecentChanges'))*/);
417    echo "</dl>\n";
418    EndLoadDump();
419 }
420
421 function SetupWiki ($dbi)
422 {
423     global $GenericPages, $LANG, $user;
424
425     //FIXME: This is a hack
426     $user->userid = 'The PhpWiki programming team';
427    
428     StartLoadDump('Loading up virgin wiki');
429     echo "<dl>\n";
430
431     LoadAny($dbi, FindLocalizedFile(WIKI_PGSRC)/*, false, $ignore*/);
432     if ($LANG != "C")
433         LoadAny($dbi, FindFile(DEFAULT_WIKI_PGSRC), $GenericPages/*, $ignore*/);
434
435     echo "</dl>\n";
436     EndLoadDump();
437 }
438
439 function LoadPostFile ($dbi, $request)
440 {
441     $upload = $request->getUploadedFile('file');
442
443     if (!$upload)
444         ExitWiki('No uploaded file to upload?');
445
446     // Dump http headers.
447     StartLoadDump("Uploading " . $upload->getName());
448     echo "<dl>\n";
449    
450     $fd = $upload->open();
451     if (IsZipFile($fd))
452         LoadZip($dbi, $fd, false, array(gettext('RecentChanges')));
453     else
454         Loadfile($dbi, $upload->getName(), $upload->getContents());
455
456     echo "</dl>\n";
457     EndLoadDump();
458 }
459
460 // For emacs users
461 // Local Variables:
462 // mode: php
463 // tab-width: 8
464 // c-basic-offset: 4
465 // c-hanging-comment-ender-p: nil
466 // indent-tabs-mode: nil
467 // End:   
468 ?>