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