4 Allows to download a tarball including all WikiPages and images that
5 currently are in the database.
10 $ewiki_t["en"]["WIKIDUMP"] = "Here you can tailor your WikiDump to your needs. <br /> When you are ready, click the \"_{DOWNLOAD_ARCHIVE}\" button.";
11 $ewiki_t["en"]["DOWNLOAD_ARCHIVE"] = "Download WikiDump";
13 define("EWIKI_WIKIDUMP_ARCNAME", "WikiDump_");
14 define("EWIKI_WIKIDUMP_DEFAULTTYPE", "TAR");
15 define("EWIKI_WIKIDUMP_MAXLEVEL", 1);
16 define('EWIKI_DUMP_FILENAME_REGEX',"/\W/");
19 if((function_exists(gzcompress) && EWIKI_WIKIDUMP_DEFAULTTYPE=="ZIP") || EWIKI_WIKIDUMP_DEFAULTTYPE=="TAR"){
20 $ewiki_plugins["page"]["WikiDump"] = "ewiki_page_wiki_dump_tarball";
21 $ewiki_plugins["action"]['wikidump'] = "ewiki_page_wiki_dump_tarball";
24 $ewiki_t["c"]["EWIKIDUMPCSS"] = '
25 <style TYPE="text/css">
28 background-color:#eeeeff;
35 border:1px solid #000000;
42 function ewiki_page_wiki_dump_tarball($id=0, $data=0, $action=0) {
44 #-- return legacy page
45 if (empty($_REQUEST["download_tarball"])) {
46 if($action=="wikidump"){
47 $url = ewiki_script("", "WikiDump");
48 return(ewiki_make_title($id, $id, 2) . ewiki_t(<<<END
51 <form action="$url" method="POST" enctype="multipart/form-data">
52 <input type="hidden" name="dump_id" value="$id">
53 <input type="hidden" name="dump_depth" value=1>
54 <input type="submit" name="download_tarball" value= "_{DOWNLOAD_ARCHIVE}">
56 <input type="checkbox" name="dump_images" value="1" checked> _{with images}<br />
57 <input type="hidden" name="dump_fullhtml" value="1">
58 <input type="hidden" name="dump_virtual" value="0"><br />
60 <select NAME="dump_arctype">
61 <option VALUE="ZIP">ZIP
62 <option VALUE="TAR">TAR
72 #-- tarball generation
74 $di = $_REQUEST["dump_images"];
75 $fh = $_REQUEST["dump_fullhtml"];
76 $vp = $_REQUEST["dump_virtual"];
77 $rp = $_REQUEST["dump_id"];
79 #-- $_REQUEST["dump_depth"]==100 will give a complete dump
80 if(($_REQUEST["dump_depth"]>EWIKI_WIKIDUMP_MAXLEVEL) && ($_REQUEST["dump_depth"]!=100)){
81 $dd=EWIKI_WIKIDUMP_MAXLEVEL;
83 $dd = $_REQUEST["dump_depth"];
85 $at = $_REQUEST["dump_arctype"];
86 $al = 9;#$_REQUEST["dump_arclevel"];
87 $_REQUEST = $_GET = $_POST = array();
88 if(!ewiki_auth($rp, $str_null, "view")){
89 return ewiki_make_title($id, $id, 2)."<p>You either do not have permission to access the page $rp or it does not exist.</p>";
91 ewiki_page_wiki_dump_send($di, $fh, $vp, $rp, $dd, $at, $al);
96 function ewiki_page_wiki_dump_send($imgs=1, $fullhtml=0, $virtual=0, $rootid, $depth=1, $arctype=EWIKI_WIKIDUMP_DEFAULTTYPE, $complevel=1) {
98 global $ewiki_config, $ewiki_plugins;
100 #-- disable protected email
101 foreach($ewiki_plugins["link_url"] as $key => $linkplugin){
102 if($linkplugin == "ewiki_email_protect_link"){
103 unset($ewiki_plugins["link_url"][$key]);
108 $a_uservars = ewiki_get_uservar("WikiDump", array());
109 if(!is_array($a_uservars)){
110 $a_uservars = unserialize($a_uservars);
112 $a_uservars[$rootid] = $depth;
113 ewiki_set_uservar("WikiDump", $a_uservars);
116 $HTML_TEMPLATE = '<html>
117 <head>'.ewiki_t("EWIKIDUMPCSS").'
118 <title>$title</title>
120 <body bgcolor="#ffffff";>
129 #-- reconfigure ewiki_format() to generate offline pages and files
134 $ewiki_config["script"] = "%s$html_ext";
135 $ewiki_config["script_binary"] = "%s";
137 #-- fetch also dynamic pages
138 $a_virtual = array_keys($ewiki_plugins["page"]);
141 #-- get all pages / binary files
142 $a_validpages = ewiki_valid_pages(1, $virtual);
143 $a_pagelist = ewiki_sitemap_create($rootid, $a_validpages, $depth, 1);
145 foreach($a_pagelist as $key => $value){
146 if(is_array($a_validpages[$value]["refs"])){
147 foreach($a_validpages[$value]["refs"] as $refs){
148 if($a_validpages[$refs]["type"]=="image"){
155 foreach($a_pagelist as $key => $value){
156 if($a_validpages[$value]["type"]=="image"){
157 $a_images[]=urlencode($value);
158 $a_rimages[]=urlencode(preg_replace(EWIKI_DUMP_FILENAME_REGEX, "", $value));
159 unset($a_validpages[$value]);
163 $a_sitemap = ewiki_sitemap_create($rootid, $a_validpages, $depth, 0);
166 #-- create new zip file
167 if($arctype == "ZIP"){
168 $archivename=EWIKI_WIKIDUMP_ARCNAME."$rootid.zip";
169 $archive = new ewiki_virtual_zip();
170 } elseif ($arctype == "TAR") {
171 $archivename=EWIKI_WIKIDUMP_ARCNAME."$rootid.tar";
172 $archive = new ewiki_virtual_tarball();
177 $a_pagelist = array_unique($a_pagelist);
179 #-- convert all pages
180 foreach($a_pagelist as $pagename){
181 if ((!in_array($pagename, $a_virtual))) {
183 #-- not a virtual page
184 $row = ewiki_db::GET($pagename);
188 #-- is a virtual page
189 $pf = $ewiki_plugins["page"][$id];
190 $content = $pf($id, $content, "view");
192 $content = str_replace('$content', $content, str_replace('$title', $id, $HTML_TEMPLATE));
194 $fn = urlencode($id);
195 $fn = preg_replace(EWIKI_DUMP_FILENAME_REGEX, "", $fn);
201 if (empty($content)){
202 switch ($row["flags"] & EWIKI_DB_F_TYPE) {
203 case (EWIKI_DB_F_TEXT):
204 $content = ewiki_format($row["content"]);
205 $content = str_replace($a_images, $a_rimages, $content);
206 $fn = preg_replace(EWIKI_DUMP_FILENAME_REGEX, "", urlencode($id));
209 $content = str_replace('$content', $content, str_replace('$title', $id, $HTML_TEMPLATE));
213 case (EWIKI_DB_F_BINARY):
214 if (($row["meta"]["class"]=="image") && ($imgs)) {
215 $fn = urlencode(preg_replace(EWIKI_DUMP_FILENAME_REGEX, "", $id));
216 $content = &$row["content"];
219 #-- php considers switch statements as loops so continue 2 is needed to
220 #-- hit the end of the for loop
231 $content=preg_replace_callback(
232 '/(<a href=")(.*?)(\.html">)/',
234 // single quotes are essential here,
235 // or alternative escape all $ as \$
237 'return($matches[1].preg_replace(EWIKI_DUMP_FILENAME_REGEX,"",$matches[2]).$matches[3]);'
243 $archive->add($content, $fn, array(
244 "mtime" => $row["lastmodified"],
246 "mode" => 0664 | (($row["flags"]&EWIKI_DB_F_WRITEABLE)?0002:0000),
250 #-- create index page
254 $str_formatted="<ul>\n<li><a href=\"".$rootid.$html_ext."\">".$rootid."</a></li>";
255 $fin_level=format_sitemap($a_sitemap, $rootid, $str_formatted, $level, $timer, $fordump);
256 $str_formatted.="</ul>".str_pad("", $fin_level*6, "</ul>\n");
257 $str_formatted=preg_replace_callback(
258 '/(<a href=")(.*?)(\.html">)/',
260 // single quotes are essential here,
261 // or alternative escape all $ as \$
263 'return($matches[1].preg_replace(EWIKI_DUMP_FILENAME_REGEX,"",$matches[2]).$matches[3]);'
269 $archive->add($str_formatted, "Index_$rootid".$html_ext, array(
270 "mtime" => $row["lastmodified"],
272 "mode" => 0664 | (($row["flags"]&EWIKI_DB_F_WRITEABLE)?0002:0000),
276 Header("Content-type: application/octet-stream");
277 Header("Content-disposition: attachment; filename=\"$archivename\"");
278 Header("Cache-control: private");
279 Header("Original-Filename: $archivename");
280 Header("X-Content-Type: application/octet-stream");
281 Header("Content-Location: $archivename");
285 echo $archive->close();
296 ############################################################################
301 #-- allows to generate a tarball from virtual files
302 # (supports no directories or symlinks and other stuff)
303 class ewiki_virtual_tarball {
306 var $datasec = array();
310 $this->write(str_repeat("\000", 9*1024));
311 $data = implode("", $this -> datasec);
316 function write($str) {
317 $this ->datasec[] = $str;
321 function oct($int, $len) {
324 $o = ($int & 0x07) . $o;
332 function add($content, $filename, $args=array(), $ignored) {
333 $args = array_merge($args, array(
337 "uid" => 65534, #-- common for user "nobody"
343 $args["mode"] |= 0100000;
344 $args["size"] = strlen($content);
346 $magic = "ustar \000";
347 $filename = substr($filename, 0, 99);
350 $header = str_pad($filename, 100, "\000") # 0x0000
351 . $this->oct($args["mode"], 8) # 0x0064
352 . $this->oct($args["uid"], 8) # 0x006C
353 . $this->oct($args["gid"], 8) # 0x0074
354 . $this->oct($args["size"], 12) # 0x007C
355 . $this->oct($args["mtime"], 12) # 0x0088
356 . ($checksum) # 0x0094
357 . ($args["type"]) # 0x009C
358 . str_repeat("\000", 100) # 0x009D
360 . str_pad($args["uname"], 32, "\000") # 0x0109
361 . str_pad($args["gname"], 32, "\000") # 0x0129
363 $header = str_pad($header, 512, "\000");
365 #-- calculate and add header checksum
367 for ($n=0; $n<512; $n++) {
368 $cksum += ord($header[$n]);
370 $header = substr($header, 0, 0x0094)
371 . $this->oct($cksum, 7) . " "
372 . substr($header, 0x009C);
375 if ($fill = (512 - (strlen($content) % 512))) {
376 $content .= str_repeat("\000", $fill);
378 $this->write($header . $content);
383 class ewiki_virtual_zip
385 var $datasec = array();
386 var $ctrl_dir = array();
387 var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
390 function add($data, $name, $ignored, $complevel) {
391 $name = str_replace("\\", "/", $name);
392 $unc_len = strlen($data);
394 $zdata = gzcompress($data, $complevel);
395 $zdata = substr ($zdata, 2, -4);
396 $c_len = strlen($zdata);
397 $fr = "\x50\x4b\x03\x04";
401 $fr .= "\x00\x00\x00\x00";
402 $fr .= pack("V",$crc);
403 $fr .= pack("V",$c_len);
404 $fr .= pack("V",$unc_len);
405 $fr .= pack("v", strlen($name) );
406 $fr .= pack("v", 0 );
409 $fr .= pack("V",$crc);
410 $fr .= pack("V",$c_len);
411 $fr .= pack("V",$unc_len);
413 $this -> datasec[] = $fr;
414 $new_offset = strlen(implode("", $this->datasec));
416 $cdrec = "\x50\x4b\x01\x02";
421 $cdrec .="\x00\x00\x00\x00";
422 $cdrec .= pack("V",$crc);
423 $cdrec .= pack("V",$c_len);
424 $cdrec .= pack("V",$unc_len);
425 $cdrec .= pack("v", strlen($name) );
426 $cdrec .= pack("v", 0 );
427 $cdrec .= pack("v", 0 );
428 $cdrec .= pack("v", 0 );
429 $cdrec .= pack("v", 0 );
430 $cdrec .= pack("V", 32 );
431 $cdrec .= pack("V", $this -> old_offset );
433 $this -> old_offset = $new_offset;
436 $this -> ctrl_dir[] = $cdrec;
440 $data = implode("", $this -> datasec);
441 $ctrldir = implode("", $this -> ctrl_dir);
446 $this -> eof_ctrl_dir .
447 pack("v", sizeof($this -> ctrl_dir)) .
448 pack("v", sizeof($this -> ctrl_dir)) .
449 pack("V", strlen($ctrldir)) .
450 pack("V", strlen($data)) .