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