]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/loadsave.php
log
[SourceForge/phpwiki.git] / lib / loadsave.php
1 <?php
2 rcs_id('$Id: loadsave.php,v 1.2 2001-02-13 05:54:38 dairiki Exp $');
3
4 require "lib/ziplib.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 function EndLoadDump()
13 {
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";
18 }
19
20    
21 ////////////////////////////////////////////////////////////////
22 //
23 //  Functions for dumping.
24 //
25 ////////////////////////////////////////////////////////////////
26
27 function MailifyPage ($pagehash, $oldpagehash = false)
28 {
29    global $SERVER_ADMIN, $ArchivePageStore;
30   
31    $from = isset($SERVER_ADMIN) ? $SERVER_ADMIN : 'foo@bar';
32   
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);
38
39    if (is_array($oldpagehash))
40    {
41       return $head . MimeMultipart(array(MimeifyPage($oldpagehash),
42                                          MimeifyPage($pagehash)));
43    }
44
45    return $head . MimeifyPage($pagehash);
46 }
47
48 /**
49  * The main() function which generates a zip archive of a PhpWiki.
50  *
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
53  * included as well.
54  */
55 function MakeWikiZip ($dbi, $include_archive = false)
56 {
57    global $WikiPageStore, $ArchivePageStore;
58   
59    $pages = GetAllWikiPageNames($dbi);
60    $zipname = "wiki.zip";
61   
62    if ($include_archive) {
63       $zipname = "wikidb.zip";
64    }
65
66    $zip = new ZipWriter("Created by PhpWiki", $zipname);
67
68    for (reset($pages); $pagename = current($pages); next($pages))
69    {
70       set_time_limit(30);       // Reset watchdog.
71       $pagehash = RetrievePage($dbi, $pagename, $WikiPageStore);
72
73       if (! is_array($pagehash))
74          continue;
75
76       if ($include_archive)
77          $oldpagehash = RetrievePage($dbi, $pagename, $ArchivePageStore);
78       else
79          $oldpagehash = false;
80
81       $attrib = array('mtime' => $pagehash['lastmodified'],
82                       'is_ascii' => 1);
83       if (($pagehash['flags'] & FLAG_PAGE_LOCKED) != 0)
84          $attrib['write_protected'] = 1;
85
86       $content = MailifyPage($pagehash, $oldpagehash);
87                      
88       $zip->addRegularFile( rawurlencode($pagehash['pagename']),
89                             $content, $attrib);
90    }
91    $zip->finish();
92 }
93
94 function DumpToDir ($dbi, $directory) 
95 {
96    global $WikiPageStore;
97
98    if (empty($directory))
99       ExitWiki(gettext("You must specify a directory to dump to"));
100    
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");
105       else
106          $html = "Created directory '$directory' for the page dump...<br>\n";
107    } else {
108       $html = "Using directory '$directory'<br>\n";
109    }
110
111    StartLoadDump("Dumping Pages", $html);
112    
113    $pages = GetAllWikiPagenames($dbi);
114
115    while (list ($i, $pagename) = each($pages))
116    {
117       $enc_name = htmlspecialchars($pagename);
118       $filename = rawurlencode($pagename);
119
120       echo "<br>$enc_name ... ";
121       if($pagename != $filename)
122          echo "<small>saved as $filename</small> ... ";
123
124       $page = RetrievePage($dbi, $pagename, $WikiPageStore);
125
126       //$data = serialize($page);
127       $data = MailifyPage($page);
128       
129       if ( !($fd = fopen("$directory/$filename", "w")) )
130          ExitWiki("<b>couldn't open file '$directory/$filename' for writing</b>\n");
131       
132       $num = fwrite($fd, $data, strlen($data));
133       echo "<small>$num bytes written</small>\n";
134       flush();
135       
136       assert($num == strlen($data));
137       fclose($fd);
138    }
139
140    EndLoadDump();
141 }
142
143 ////////////////////////////////////////////////////////////////
144 //
145 //  Functions for restoring.
146 //
147 ////////////////////////////////////////////////////////////////
148
149 function SavePage ($dbi, $page, $defaults, $source, $filename)
150 {
151    global $WikiPageStore;
152
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]))
157          $page[$key] = $val;
158
159    $pagename = $page['pagename'];
160
161    if (empty($pagename))
162    {
163       echo Element('dd'). Element('dt', QElement('b', "Empty pagename!"));
164       return;
165    }
166    
167    
168    $mesg = array();
169    $version = $page['version'];
170    $isnew = true;
171    
172    if ($version)
173       $mesg[] = sprintf(gettext("version %s"), $version);
174    if ($source)
175       $mesg[] = sprintf(gettext("from %s"), $source);
176   
177    if (is_array($current = RetrievePage($dbi, $pagename, $WikiPageStore)))
178    {
179       $isnew = false;
180       
181       if (arrays_equal($current['content'], $page['content'])
182           && $current['author'] == $page['author']
183           && $current['flags'] == $page['flags'])
184       {
185          $mesg[] = sprintf(gettext("is identical to current version %d"),
186                            $current['version']);
187
188          if ( $version <= $current['version'] )
189          {
190             $mesg[] = gettext("- skipped");
191             $page = false;
192          }
193       }
194       else
195       {
196          SaveCopyToArchive($dbi, $pagename, $current);
197
198          if ( $version <= $current['version'] )
199             $page['version'] = $current['version'] + 1;
200       }
201    }
202    else if ($page['version'] < 1)
203       $page['version'] = 1;
204    
205
206    if ($page)
207    {
208       InsertPage($dbi, $pagename, $page);
209       UpdateRecentChanges($dbi, $pagename, $isnew);
210       
211       $mesg[] = gettext("- saved");
212       if ($version != $page['version'])
213          $mesg[] = sprintf(gettext("as version %d"), $page['version']);
214    }
215    
216    print( Element('dt', LinkExistingWikiWord($pagename))
217           . QElement('dd', join(" ", $mesg))
218           . "\n" );
219    flush();
220 }
221
222 function ParseSerializedPage($text)
223 {
224    if (!preg_match('/^a:\d+:{[si]:\d+/', $text))
225       return false;
226    return unserialize($text);
227 }
228  
229 function SortByPageVersion ($a, $b) {
230    return $a['version'] - $b['version'];
231 }
232
233 function LoadFile ($dbi, $filename, $text = false, $mtime = false)
234 {
235    if (!is_string($text))
236    {
237       // Read the file.
238       $stat = stat($filename);
239       $mtime = $stat[9];
240       $text = implode("", file($filename));
241    }
242    
243    set_time_limit(30);  // Reset watchdog.
244
245    // FIXME: basename("filewithnoslashes") seems to return garbage sometimes.
246    $basename = basename("/dummy/" . $filename);
247    
248    if (!$mtime)
249       $mtime = time();  // Last resort.
250
251    $defaults = array('author' => $GLOBALS['user']->id(),
252                      'pagename' => rawurldecode($basename),
253                      'flags' => 0,
254                      'version' => 0,
255                      'created' => $mtime,
256                      'lastmodified' => $mtime);
257
258    if ( ($parts = ParseMimeifiedPages($text)) )
259    {
260       usort($parts, 'SortByPageVersion');
261       for (reset($parts); $page = current($parts); next($parts))
262          SavePage($dbi, $page, $defaults, "MIME file $filename", $basename);
263    }
264    else if ( ($page = ParseSerializedPage($text)) )
265    {
266       SavePage($dbi, $page, $defaults, "Serialized file $filename", $basename);
267    }
268    else
269    {
270       // Assume plain text file.
271       $page['content'] = preg_split('/[ \t\r]*\n/', chop($text));
272       SavePage($dbi, $page, $defaults, "plain file $filename", $basename);
273    }
274 }
275
276 function LoadZip ($dbi, $zipfile, $files = false, $exclude = false)
277 {
278    $zip = new ZipReader($zipfile);
279    while (list ($fn, $data, $attrib) = $zip->readFile())
280    {
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)) )
285       {
286          print Element('dt', LinkExistingWikiWord($fn)) . QElement('dd', 'Skipping');
287          continue;
288       }
289
290       LoadFile($dbi, $fn, $data, $attrib['mtime']);
291    }
292 }
293
294 function LoadDir ($dbi, $dirname, $files = false, $exclude = false)
295 {
296    $handle = opendir($dir = $dirname);
297    while ($fn = readdir($handle))
298    {
299       if (filetype("$dir/$fn") != 'file')
300          continue;
301
302       if ( ($files && !in_array($fn, $files))
303            || ($exclude && in_array($fn, $exclude)) )
304       {
305          print Element('dt', LinkExistingWikiWord($fn)) . QElement('dd', 'Skipping');
306          continue;
307       }
308       
309       LoadFile($dbi, "$dir/$fn");
310    }
311    closedir($handle);
312 }
313
314 function IsZipFile ($filename_or_fd)
315 {
316    // See if it looks like zip file
317    if (is_string($filename_or_fd))
318    {
319       $fd = fopen($filename_or_fd, "rb");
320       $magic = fread($fd, 4);
321       fclose($fd);
322    }
323    else
324    {
325       $fpos = ftell($filename_or_fd);
326       $magic = fread($filename_or_fd, 4);
327       fseek($filename_or_fd, $fpos);
328    }
329    
330    return $magic == ZIP_LOCHEAD_MAGIC || $magic == ZIP_CENTHEAD_MAGIC;
331 }
332
333    
334 function LoadAny ($dbi, $file_or_dir, $files = false, $exclude = false)
335 {
336    $type = filetype($file_or_dir);
337
338    if ($type == 'dir')
339    {
340       LoadDir($dbi, $file_or_dir, $files, $exclude);
341    }
342    else if ($type != 'file' && !preg_match('/^(http|ftp):/', $file_or_dir))
343    {
344       ExitWiki("Bad file type: $type");
345    }
346    else if (IsZipFile($file_or_dir))
347    {
348       LoadZip($dbi, $file_or_dir, $files, $exclude);
349    }
350    else /* if (!$files || in_array(basename($file_or_dir), $files)) */
351    {
352       LoadFile($dbi, $file_or_dir);
353    }
354 }
355
356 function LoadFileOrDir ($dbi, $source)
357 {
358    StartLoadDump("Loading '$source'");
359    echo "<dl>\n";
360    LoadAny($dbi, $source, false, array(gettext('RecentChanges')));
361    echo "</dl>\n";
362    EndLoadDump();
363 }
364
365 function SetupWiki ($dbi)
366 {
367    global $GenericPages, $LANG, $user;
368
369    //FIXME: This is a hack
370    $user->userid = 'The PhpWiki programming team';
371    
372    StartLoadDump('Loading up virgin wiki');
373    echo "<dl>\n";
374
375    LoadAny($dbi, SearchPath(WIKI_PGSRC));
376    if ($LANG != "C")
377       LoadAny($dbi, SearchPath(DEFAULT_WIKI_PGSRC), $GenericPages);
378
379    echo "</dl>\n";
380    EndLoadDump();
381 }
382
383 function LoadPostFile ($dbi, $postname)
384 {
385    global $HTTP_POST_FILES;
386
387    extract($HTTP_POST_FILES[$postname]);
388    fix_magic_quotes_gpc($tmp_name);
389    fix_magic_quotes_gpc($name);
390
391    if (!is_uploaded_file($tmp_name))
392       ExitWiki('Bad file post');        // Possible malicious attack.
393    
394    // Dump http headers.
395    $fd = fopen($tmp_name, "rb");
396    while ( ($header = fgets($fd, 4096)) )
397       if (trim($header) == '')
398          break;
399
400    StartLoadDump("Uploading $name");
401    echo "<dl>\n";
402    
403    if (IsZipFile($fd))
404       LoadZip($dbi, $fd, false, array(gettext('RecentChanges')));
405    else
406       Loadfile($dbi, $name, fread($fd, MAX_UPLOAD_SIZE));
407
408    echo "</dl>\n";
409    EndLoadDump();
410 }
411
412 // For emacs users
413 // Local Variables:
414 // mode: php
415 // c-file-style: "ellemtel"
416 // End:   
417 ?>