OSDN Git Service

1.4.5_1
[pukiwiki/pukiwiki.git] / plugin / dump.inc.php
1 <?php
2 // $Id: dump.inc.php,v 1.34 2005/01/23 07:24:11 henoheno Exp $
3 //
4 // Remote dump / restore plugin
5 // Originated as tarfile.inc.php by teanan / Interfair Laboratory 2004.
6
7 /////////////////////////////////////////////////
8 // User defines
9
10 // Allow using resture function
11 define('PLUGIN_DUMP_ALLOW_RESTORE', FALSE); // FALSE, TRUE
12
13 // ¥Ú¡¼¥¸Ì¾¤ò¥Ç¥£¥ì¥¯¥È¥ê¹½Â¤¤ËÊÑ´¹¤¹¤ëºÝ¤Îʸ»ú¥³¡¼¥É (for mbstring)
14 define('PLUGIN_DUMP_FILENAME_ENCORDING', 'SJIS');
15
16 // ºÇÂ祢¥Ã¥×¥í¡¼¥É¥µ¥¤¥º
17 define('PLUGIN_DUMP_MAX_FILESIZE', 1024); // Kbyte
18
19 /////////////////////////////////////////////////
20 // Internal defines
21
22 // Action
23 define('PLUGIN_DUMP_DUMP',    'dump');    // Dump & download
24 define('PLUGIN_DUMP_RESTORE', 'restore'); // Upload & restore
25
26 global $_STORAGE;
27
28 // DATA_DIR (wiki/*.txt)
29 $_STORAGE['DATA_DIR']['add_filter']     = '^[0-9A-F]+\.txt';
30 $_STORAGE['DATA_DIR']['extract_filter'] = '^' . preg_quote(DATA_DIR, '/')   . '((?:[0-9A-F])+)(\.txt){0,1}';
31
32 // UPLOAD_DIR (attach/*)
33 $_STORAGE['UPLOAD_DIR']['add_filter']     = '^[0-9A-F_]+';
34 $_STORAGE['UPLOAD_DIR']['extract_filter'] = '^' . preg_quote(UPLOAD_DIR, '/') . '((?:[0-9A-F]{2})+)_((?:[0-9A-F])+)';
35
36 // BACKUP_DIR (backup/*.gz)
37 $_STORAGE['BACKUP_DIR']['add_filter']     = '^[0-9A-F]+\.gz';
38 $_STORAGE['BACKUP_DIR']['extract_filter'] =  '^' . preg_quote(BACKUP_DIR, '/') . '((?:[0-9A-F])+)(\.gz){0,1}';
39
40
41 /////////////////////////////////////////////////
42 // ¥×¥é¥°¥¤¥óËÜÂÎ
43 function plugin_dump_action()
44 {
45         global $vars;
46
47         if (PKWK_READONLY) die_message('PKWK_READONLY prohibits this');
48
49         $pass = isset($_POST['pass']) ? $_POST['pass'] : NULL;
50         $act  = isset($vars['act'])   ? $vars['act']   : NULL;
51
52         $body = '';
53
54         if ($pass !== NULL) {
55                 if (! pkwk_login($pass)) {
56                         $body = "<p><strong>¥Ñ¥¹¥ï¡¼¥É¤¬°ã¤¤¤Þ¤¹¡£</strong></p>\n";
57                 } else {
58                         switch($act){
59                         case PLUGIN_DUMP_DUMP:
60                                 $body = plugin_dump_download();
61                                 break;
62                         case PLUGIN_DUMP_RESTORE:
63                                 $retcode = plugin_dump_upload();
64                                 if ($retcode['code'] == TRUE) {
65                                         $msg = '¥¢¥Ã¥×¥í¡¼¥É¤¬´°Î»¤·¤Þ¤·¤¿';
66                                 } else {
67                                         $msg = '¥¢¥Ã¥×¥í¡¼¥É¤Ë¼ºÇÔ¤·¤Þ¤·¤¿';
68                                 }
69                                 $body .= $retcode['msg'];
70                                 return array('msg' => $msg, 'body' => $body);
71                                 break;
72                         }
73                 }
74         }
75
76         // ÆþÎÏ¥Õ¥©¡¼¥à¤òɽ¼¨
77         $body .= plugin_dump_disp_form();
78
79         $msg = '';
80         if (PLUGIN_DUMP_ALLOW_RESTORE) {
81                 $msg = 'dump & restore';
82         } else {
83                 $msg = 'dump';
84         }
85
86         return array('msg' => $msg, 'body' => $body);
87 }
88
89 /////////////////////////////////////////////////
90 // ¥Õ¥¡¥¤¥ë¤Î¥À¥¦¥ó¥í¡¼¥É
91 function plugin_dump_download()
92 {
93         global $vars, $_STORAGE;
94
95         // ¥¢¡¼¥«¥¤¥Ö¤Î¼ïÎà
96         $arc_kind = ($vars['pcmd'] == 'tar') ? 'tar' : 'tgz';
97
98         // ¥Ú¡¼¥¸Ì¾¤ËÊÑ´¹¤¹¤ë
99         $namedecode = isset($vars['namedecode']) ? TRUE : FALSE;
100
101         // ¥Ð¥Ã¥¯¥¢¥Ã¥×¥Ç¥£¥ì¥¯¥È¥ê
102         $bk_wiki   = isset($vars['bk_wiki'])   ? TRUE : FALSE;
103         $bk_attach = isset($vars['bk_attach']) ? TRUE : FALSE;
104         $bk_backup = isset($vars['bk_backup']) ? TRUE : FALSE;
105
106         $filecount = 0;
107         $tar = new tarlib();
108         $tar->create(CACHE_DIR, $arc_kind) or
109                 die_message('¥Æ¥ó¥Ý¥é¥ê¥Õ¥¡¥¤¥ë¤ÎÀ¸À®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿¡£');
110
111         if ($bk_wiki)   $filecount += $tar->add_dir(DATA_DIR,   $_STORAGE['DATA_DIR']['add_filter'],   $namedecode);
112         if ($bk_attach) $filecount += $tar->add_dir(UPLOAD_DIR, $_STORAGE['UPLOAD_DIR']['add_filter'], $namedecode);
113         if ($bk_backup) $filecount += $tar->add_dir(BACKUP_DIR, $_STORAGE['BACKUP_DIR']['add_filter'], $namedecode);
114
115         $tar->close();
116
117         if ($filecount === 0) {
118                 @unlink($tar->filename);
119                 return '<p><strong>¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£</strong></p>';
120         } else {
121                 // ¥À¥¦¥ó¥í¡¼¥É
122                 download_tarfile($tar->filename, $arc_kind);
123                 @unlink($tar->filename);
124                 exit;   // Àµ¾ï½ªÎ»
125         }
126 }
127
128 /////////////////////////////////////////////////
129 // ¥Õ¥¡¥¤¥ë¤Î¥¢¥Ã¥×¥í¡¼¥É
130 function plugin_dump_upload()
131 {
132         global $vars, $_STORAGE;
133
134         if (! PLUGIN_DUMP_ALLOW_RESTORE)
135                 return array('code' => FALSE , 'msg' => 'Restoring function is not allowed');
136
137         $filename = $_FILES['upload_file']['name'];
138         $matches  = array();
139         $arc_kind = FALSE;
140         if(! preg_match('/(\.tar|\.tar.gz|\.tgz)$/', $filename, $matches)){
141                 die_message('Invalid file suffix');
142         } else { 
143                 $matches[1] = strtolower($matches[1]);
144                 switch ($matches[1]) {
145                 case '.tar':    $arc_kind = 'tar'; break;
146                 case '.tgz':    $arc_kind = 'tar'; break;
147                 case '.tar.gz': $arc_kind = 'tgz'; break;
148                 default: die_message('Invalid file suffix: ' . $matches[1]); }
149         }
150
151         if ($_FILES['upload_file']['size'] >  PLUGIN_DUMP_MAX_FILESIZE * 1024)
152                 die_message('Max file size exceeded: ' . PLUGIN_DUMP_MAX_FILESIZE . 'KB');
153
154         // Create a temporary tar file
155         $uploadfile = tempnam(CACHE_DIR, 'tarlib_uploaded_');
156         $tar = new tarlib();
157         if(! move_uploaded_file($_FILES['upload_file']['tmp_name'], $uploadfile) ||
158            ! $tar->open($uploadfile, $arc_kind)) {
159                 @unlink($uploadfile);
160                 die_message('¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£');
161         }
162
163         $pattern = "(({$_STORAGE['DATA_DIR']['extract_filter']})|" .
164                     "({$_STORAGE['UPLOAD_DIR']['extract_filter']})|" .
165                     "({$_STORAGE['BACKUP_DIR']['extract_filter']}))";
166         $files = $tar->extract($pattern);
167         if (empty($files)) {
168                 @unlink($uploadfile);
169                 return array('code' => FALSE, 'msg' => '<p>Ÿ³«¤Ç¤­¤ë¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£</p>');
170         }
171
172         $msg  = '<p><strong>Ÿ³«¤·¤¿¥Õ¥¡¥¤¥ë°ìÍ÷</strong><ul>';
173         foreach($files as $name) {
174                 $msg .= "<li>$name</li>\n";
175         }
176         $msg .= '</ul></p>';
177
178         $tar->close();
179         @unlink($uploadfile);
180
181         return array('code' => TRUE, 'msg' => $msg);
182 }
183
184 /////////////////////////////////////////////////
185 // tar¥Õ¥¡¥¤¥ë¤Î¥À¥¦¥ó¥í¡¼¥É
186 function download_tarfile($tempnam, $arc_kind)
187 {
188         $size = filesize($tempnam);
189
190         $filename = strftime('tar%Y%m%d', time());
191         if ($arc_kind == 'tgz') {
192                 $filename .= '.tar.gz';
193         } else {
194                 $filename .= '.tar';
195         }
196
197         pkwk_common_headers();
198         header('Content-Disposition: attachment; filename="' . $filename . '"');
199         header('Content-Length: ' . $size);
200         header('Content-Type: application/octet-stream');
201         header('Pragma: no-cache');
202         @readfile($tempnam);
203 }
204
205 /////////////////////////////////////////////////
206 // ÆþÎÏ¥Õ¥©¡¼¥à¤òɽ¼¨
207 function plugin_dump_disp_form()
208 {
209         global $script, $defaultpage;
210
211         $act_down = PLUGIN_DUMP_DUMP;
212         $act_up   = PLUGIN_DUMP_RESTORE;
213         $maxsize  = PLUGIN_DUMP_MAX_FILESIZE;
214
215         $data = <<<EOD
216 <span class="small">
217 </span>
218 <h3>¥Ç¡¼¥¿¤Î¥À¥¦¥ó¥í¡¼¥É</h3>
219 <form action="$script" method="post">
220  <div>
221   <input type="hidden" name="cmd"  value="dump" />
222   <input type="hidden" name="page" value="$defaultpage" />
223   <input type="hidden" name="act"  value="$act_down" />
224
225 <p><strong>¥¢¡¼¥«¥¤¥Ö¤Î·Á¼°</strong>
226 <br />
227   <input type="radio" name="pcmd" value="tgz" checked="checked" /> ¡Á.tar.gz ·Á¼°<br />
228   <input type="radio" name="pcmd" value="tar" /> ¡Á.tar ·Á¼°
229 </p>
230 <p><strong>¥Ð¥Ã¥¯¥¢¥Ã¥×¥Ç¥£¥ì¥¯¥È¥ê</strong>
231 <br />
232   <input type="checkbox" name="bk_wiki" checked="checked" /> wiki<br />
233   <input type="checkbox" name="bk_attach" /> attach<br />
234   <input type="checkbox" name="bk_backup" /> backup
235 </p>
236 <p><strong>¥ª¥×¥·¥ç¥ó</strong>
237 <br />
238   <input type="checkbox" name="namedecode" /> ¥¨¥ó¥³¡¼¥É¤µ¤ì¤Æ¤¤¤ë¥Ú¡¼¥¸Ì¾¤ò¥Ç¥£¥ì¥¯¥È¥ê³¬ÁؤĤ­¤Î¥Õ¥¡¥¤¥ë¤Ë¥Ç¥³¡¼¥É (¢¨¥ê¥¹¥È¥¢¤Ë»È¤¦¤³¤È¤Ï¤Ç¤­¤Ê¤¯¤Ê¤ê¤Þ¤¹¡£¤Þ¤¿¡¢°ìÉô¤Îʸ»ú¤Ï '_' ¤ËÃÖ´¹¤µ¤ì¤Þ¤¹)<br />
239 </p>
240 <p><strong>´ÉÍý¼Ô¥Ñ¥¹¥ï¡¼¥É</strong>
241   <input type="password" name="pass" size="12" />
242   <input type="submit"   name="ok"   value="OK" />
243 </p>
244  </div>
245 </form>
246 EOD;
247
248         if(PLUGIN_DUMP_ALLOW_RESTORE) {
249                 $data .= <<<EOD
250 <h3>¥Ç¡¼¥¿¤Î¥ê¥¹¥È¥¢ (*.tar, *.tar.gz)</h3>
251 <form enctype="multipart/form-data" action="$script" method="post">
252  <div>
253   <input type="hidden" name="cmd"  value="dump" />
254   <input type="hidden" name="page" value="$defaultpage" />
255   <input type="hidden" name="act"  value="$act_up" />
256 <p><strong>[½ÅÍ×] Æ±¤¸Ì¾Á°¤Î¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤Ï¾å½ñ¤­¤µ¤ì¤Þ¤¹¤Î¤Ç¡¢½½Ê¬¤´Ãí°Õ¤¯¤À¤µ¤¤¡£</strong></p>
257 <p><span class="small">
258 ¥¢¥Ã¥×¥í¡¼¥É²Äǽ¤ÊºÇÂç¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤Ï¡¢$maxsize KByte ¤Þ¤Ç¤Ç¤¹¡£<br />
259 </span>
260   ¥Õ¥¡¥¤¥ë: <input type="file" name="upload_file" size="40" />
261 </p>
262 <p><strong>´ÉÍý¼Ô¥Ñ¥¹¥ï¡¼¥É</strong>
263   <input type="password" name="pass" size="12" />
264   <input type="submit"   name="ok"   value="OK" />
265 </p>
266  </div>
267 </form>
268 EOD;
269         }
270
271         return $data;
272 }
273
274 /////////////////////////////////////////////////
275 // tarlib: a class library for tar file creation and expansion
276
277 // Tar related definition
278 define('TARLIB_HDR_LEN',           512);        // ¥Ø¥Ã¥À¤ÎÂ礭¤µ
279 define('TARLIB_BLK_LEN',           512);        // Ã±°Ì¥Ö¥í¥Ã¥¯Ä¹¤µ
280 define('TARLIB_HDR_NAME_OFFSET',     0);        // ¥Õ¥¡¥¤¥ë̾¤Î¥ª¥Õ¥»¥Ã¥È
281 define('TARLIB_HDR_NAME_LEN',      100);        // ¥Õ¥¡¥¤¥ë̾¤ÎºÇÂ獵
282 define('TARLIB_HDR_MODE_OFFSET',   100);        // mode¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
283 define('TARLIB_HDR_UID_OFFSET',    108);        // uid¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
284 define('TARLIB_HDR_GID_OFFSET',    116);        // gid¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
285 define('TARLIB_HDR_SIZE_OFFSET',   124);        // ¥µ¥¤¥º¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
286 define('TARLIB_HDR_SIZE_LEN',       12);        // ¥µ¥¤¥º¤ÎŤµ
287 define('TARLIB_HDR_MTIME_OFFSET',  136);        // ºÇ½ª¹¹¿·»þ¹ï¤Î¥ª¥Õ¥»¥Ã¥È
288 define('TARLIB_HDR_MTIME_LEN',      12);        // ºÇ½ª¹¹¿·»þ¹ï¤ÎŤµ
289 define('TARLIB_HDR_CHKSUM_OFFSET', 148);        // ¥Á¥§¥Ã¥¯¥µ¥à¤Î¥ª¥Õ¥»¥Ã¥È
290 define('TARLIB_HDR_CHKSUM_LEN',      8);        // ¥Á¥§¥Ã¥¯¥µ¥à¤ÎŤµ
291 define('TARLIB_HDR_TYPE_OFFSET',   156);        // ¥Õ¥¡¥¤¥ë¥¿¥¤¥×¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
292
293 // Status
294 define('TARLIB_STATUS_INIT',    0);             // ½é´ü¾õÂÖ
295 define('TARLIB_STATUS_OPEN',   10);             // Æɤ߼è¤ê
296 define('TARLIB_STATUS_CREATE', 20);             // ½ñ¤­¹þ¤ß
297
298 define('TARLIB_DATA_MODE',      '100666 ');     // ¥Õ¥¡¥¤¥ë¥Ñ¡¼¥ß¥Ã¥·¥ç¥ó
299 define('TARLIB_DATA_UGID',      '000000 ');     // uid / gid
300 define('TARLIB_DATA_CHKBLANKS', '        ');
301
302 // GNU³ÈÄ¥»ÅÍÍ(¥í¥ó¥°¥Õ¥¡¥¤¥ë̾Âбþ)
303 define('TARLIB_DATA_LONGLINK', '././@LongLink');
304
305 // Type flag
306 define('TARLIB_HDR_FILE', '0');
307 define('TARLIB_HDR_LINK', 'L');
308
309 // Kind of the archive
310 define('TARLIB_KIND_TGZ', 0);
311 define('TARLIB_KIND_TAR', 1);
312
313 class tarlib
314 {
315         var $filename;
316         var $fp;
317         var $status;
318         var $arc_kind;
319         var $dummydata;
320
321         // ¥³¥ó¥¹¥È¥é¥¯¥¿
322         function tarlib() {
323                 $this->filename = '';
324                 $this->fp       = FALSE;
325                 $this->status   = TARLIB_STATUS_INIT;
326                 $this->arc_kind = TARLIB_KIND_TGZ;
327         }
328         
329         ////////////////////////////////////////////////////////////
330         // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë
331         // °ú¿ô  : tar¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë¥Ñ¥¹
332         // ÊÖ¤êÃÍ: TRUE .. À®¸ù , FALSE .. ¼ºÇÔ
333         ////////////////////////////////////////////////////////////
334         function create($tempdir, $kind = 'tgz')
335         {
336                 $tempnam = tempnam($tempdir, 'tarlib_create_');
337                 if ($tempnam === FALSE) return FALSE;
338
339                 if ($kind == 'tgz') {
340                         $this->arc_kind = TARLIB_KIND_TGZ;
341                         $this->fp       = gzopen($tempnam, 'wb');
342                 } else {
343                         $this->arc_kind = TARLIB_KIND_TAR;
344                         $this->fp       = @fopen($tempnam, 'wb');
345                 }
346
347                 if ($this->fp === FALSE) {
348                         @unlink($tempnam);
349                         return FALSE;
350                 } else {
351                         $this->filename  = $tempnam;
352                         $this->dummydata = join('', array_fill(0, TARLIB_BLK_LEN, "\0"));
353                         $this->status    = TARLIB_STATUS_CREATE;
354                         rewind($this->fp);
355                         return TRUE;
356                 }
357         }
358
359         ////////////////////////////////////////////////////////////
360         // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤òÄɲ乤ë
361         // °ú¿ô  : $dir    .. ¥Ç¥£¥ì¥¯¥È¥ê̾
362         //         $mask   .. Äɲ乤ë¥Õ¥¡¥¤¥ë(Àµµ¬É½¸½)
363         //         $decode .. ¥Ú¡¼¥¸Ì¾¤ÎÊÑ´¹¤ò¤¹¤ë¤«
364         // ÊÖ¤êÃÍ: ºîÀ®¤·¤¿¥Õ¥¡¥¤¥ë¿ô
365         ////////////////////////////////////////////////////////////
366         function add_dir($dir, $mask, $decode = FALSE)
367         {
368                 $retvalue = 0;
369                 
370                 if ($this->status != TARLIB_STATUS_CREATE)
371                         return ''; // File is not created
372
373                 unset($files);
374
375                 //  »ØÄꤵ¤ì¤¿¥Ñ¥¹¤Î¥Õ¥¡¥¤¥ë¤Î¥ê¥¹¥È¤ò¼èÆÀ¤¹¤ë
376                 $dp = @opendir($dir);
377                 if($dp === FALSE) {
378                         @unlink($this->filename);
379                         die_message($dir . ' is not found or not readable.');
380                 }
381
382                 while ($filename = readdir($dp)) {
383                         if (preg_match("/$mask/", $filename))
384                                 $files[] = $dir . $filename;
385                 }
386                 closedir($dp);
387                 
388                 sort($files);
389
390                 $matches = array();
391                 foreach($files as $name)
392                 {
393                         // Tar¤Ë³ÊǼ¤¹¤ë¥Õ¥¡¥¤¥ë̾¤òdecode
394                         if ($decode === FALSE) {
395                                 $filename = $name;
396                         } else {
397                                 $dirname  = dirname(trim($name)) . '/';
398                                 $filename = basename(trim($name));
399                                 if (preg_match("/^((?:[0-9A-F]{2})+)_((?:[0-9A-F]{2})+)/", $filename, $matches)) {
400                                         // attach¥Õ¥¡¥¤¥ë̾
401                                         $filename = decode($matches[1]) . '/' . decode($matches[2]);
402                                 } else {
403                                         $pattern = '^((?:[0-9A-F]{2})+)((\.txt|\.gz)*)$';
404                                         if (preg_match("/$pattern/", $filename, $matches)) {
405                                                 $filename = decode($matches[1]) . $matches[2];
406
407                                                 // ´í¤Ê¤¤¥³¡¼¥É¤ÏÃÖ´¹¤·¤Æ¤ª¤¯
408                                                 $filename = str_replace(':',  '_', $filename);
409                                                 $filename = str_replace('\\', '_', $filename);
410                                         }
411                                 }
412                                 $filename = $dirname . $filename;
413                                 // ¥Õ¥¡¥¤¥ë̾¤Îʸ»ú¥³¡¼¥É¤òÊÑ´¹
414                                 if (function_exists('mb_convert_encoding'))
415                                         $filename = mb_convert_encoding($filename, PLUGIN_DUMP_FILENAME_ENCORDING);
416                         }
417
418                         // ºÇ½ª¹¹¿·»þ¹ï
419                         $mtime = filemtime($name);
420
421                         // ¥Õ¥¡¥¤¥ë̾Ĺ¤Î¥Á¥§¥Ã¥¯
422                         if (strlen($filename) > TARLIB_HDR_NAME_LEN) {
423                                 // LongLinkÂбþ
424                                 $size = strlen($filename);
425                                 // LonkLink¥Ø¥Ã¥ÀÀ¸À®
426                                 $tar_data = $this->_make_header(TARLIB_DATA_LONGLINK, $size, $mtime, TARLIB_HDR_LINK);
427                                 // ¥Õ¥¡¥¤¥ë½ÐÎÏ
428                                 $this->_write_data(join('', $tar_data), $filename, $size);
429                         }
430
431                         // ¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤ò¼èÆÀ
432                         $size = filesize($name);
433                         if ($size == FALSE) {
434                                 @unlink($this->filename);
435                                 die_message($name . ' is not found or not readable.');
436                         }
437
438                         // ¥Ø¥Ã¥ÀÀ¸À®
439                         $tar_data = $this->_make_header($filename, $size, $mtime, TARLIB_HDR_FILE);
440
441                         // ¥Õ¥¡¥¤¥ë¥Ç¡¼¥¿¤Î¼èÆÀ
442                         $fpr = @fopen($name , 'rb');
443                         flock($fpr, LOCK_SH);
444                         $data = fread($fpr, $size);
445                         flock($fpr, LOCK_UN);
446                         fclose( $fpr );
447
448                         // ¥Õ¥¡¥¤¥ë½ÐÎÏ
449                         $this->_write_data(join('', $tar_data), $data, $size);
450                         ++$retvalue;
451                 }
452                 return $retvalue;
453         }
454         
455         ////////////////////////////////////////////////////////////
456         // ´Ø¿ô  : tar¤Î¥Ø¥Ã¥À¾ðÊó¤òÀ¸À®¤¹¤ë (add)
457         // °ú¿ô  : $filename .. ¥Õ¥¡¥¤¥ë̾
458         //         $size     .. ¥Ç¡¼¥¿¥µ¥¤¥º
459         //         $mtime    .. ºÇ½ª¹¹¿·Æü
460         //         $typeflag .. TypeFlag (file/link)
461         // Ìá¤êÃÍ: tar¥Ø¥Ã¥À¾ðÊó
462         ////////////////////////////////////////////////////////////
463         function _make_header($filename, $size, $mtime, $typeflag)
464         {
465                 $tar_data = array_fill(0, TARLIB_HDR_LEN, "\0");
466                 
467                 // ¥Õ¥¡¥¤¥ë̾¤òÊݸ
468                 for($i = 0; $i < strlen($filename); $i++ ) {
469                         if ($i < TARLIB_HDR_NAME_LEN) {
470                                 $tar_data[$i + TARLIB_HDR_NAME_OFFSET] = $filename{$i};
471                         } else {
472                                 break;  // ¥Õ¥¡¥¤¥ë̾¤¬Ä¹¤¹¤®
473                         }
474                 }
475
476                 // mode
477                 $modeid = TARLIB_DATA_MODE;
478                 for($i = 0; $i < strlen($modeid); $i++ ) {
479                         $tar_data[$i + TARLIB_HDR_MODE_OFFSET] = $modeid{$i};
480                 }
481
482                 // uid / gid
483                 $ugid = TARLIB_DATA_UGID;
484                 for($i = 0; $i < strlen($ugid); $i++ ) {
485                         $tar_data[$i + TARLIB_HDR_UID_OFFSET] = $ugid{$i};
486                         $tar_data[$i + TARLIB_HDR_GID_OFFSET] = $ugid{$i};
487                 }
488
489                 // ¥µ¥¤¥º
490                 $strsize = sprintf('%11o', $size);
491                 for($i = 0; $i < strlen($strsize); $i++ ) {
492                         $tar_data[$i + TARLIB_HDR_SIZE_OFFSET] = $strsize{$i};
493                 }
494
495                 // ºÇ½ª¹¹¿·»þ¹ï
496                 $strmtime = sprintf('%o', $mtime);
497                 for($i = 0; $i < strlen($strmtime); $i++ ) {
498                         $tar_data[$i + TARLIB_HDR_MTIME_OFFSET] = $strmtime{$i};
499                 }
500
501                 // ¥Á¥§¥Ã¥¯¥µ¥à·×»»ÍѤΥ֥é¥ó¥¯¤òÀßÄê
502                 $chkblanks = TARLIB_DATA_CHKBLANKS;
503                 for($i = 0; $i < strlen($chkblanks); $i++ ) {
504                         $tar_data[$i + TARLIB_HDR_CHKSUM_OFFSET] = $chkblanks{$i};
505                 }
506
507                 // ¥¿¥¤¥×¥Õ¥é¥°
508                 $tar_data[TARLIB_HDR_TYPE_OFFSET] = $typeflag;
509
510                 // ¥Á¥§¥Ã¥¯¥µ¥à¤Î·×»»
511                 $sum = 0;
512                 for($i = 0; $i < TARLIB_BLK_LEN; $i++ ) {
513                         $sum += 0xff & ord($tar_data[$i]);
514                 }
515                 $strchksum = sprintf('%7o',$sum);
516                 for($i = 0; $i < strlen($strchksum); $i++ ) {
517                         $tar_data[$i + TARLIB_HDR_CHKSUM_OFFSET] = $strchksum{$i};
518                 }
519
520                 return $tar_data;
521         }
522         
523         ////////////////////////////////////////////////////////////
524         // ´Ø¿ô  : tar¥Ç¡¼¥¿¤Î¥Õ¥¡¥¤¥ë½ÐÎÏ (add)
525         // °ú¿ô  : $header .. tar¥Ø¥Ã¥À¾ðÊó
526         //         $body   .. tar¥Ç¡¼¥¿
527         //         $size   .. ¥Ç¡¼¥¿¥µ¥¤¥º
528         // Ìá¤êÃÍ: ¤Ê¤·
529         ////////////////////////////////////////////////////////////
530         function _write_data($header, $body, $size)
531         {
532                 $fixsize  = ceil($size / TARLIB_BLK_LEN) * TARLIB_BLK_LEN - $size;
533
534                 if ($this->arc_kind == TARLIB_KIND_TGZ) {
535                         gzwrite($this->fp, $header, TARLIB_HDR_LEN);    // Header
536                         gzwrite($this->fp, $body, $size);               // Body
537                         gzwrite($this->fp, $this->dummydata, $fixsize); // Padding
538                 } else {
539                          fwrite($this->fp, $header, TARLIB_HDR_LEN);    // Header
540                          fwrite($this->fp, $body, $size);               // Body
541                          fwrite($this->fp, $this->dummydata, $fixsize); // Padding
542                 }
543         }
544
545         ////////////////////////////////////////////////////////////
546         // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤ò³«¤¯
547         // °ú¿ô  : tar¥Õ¥¡¥¤¥ë̾
548         // ÊÖ¤êÃÍ: TRUE .. À®¸ù , FALSE .. ¼ºÇÔ
549         ////////////////////////////////////////////////////////////
550         function open($name = '', $kind = 'tgz')
551         {
552                 if (! PLUGIN_DUMP_ALLOW_RESTORE) return FALSE; // Not allowed
553
554                 if ($name != '') $this->filename = $name;
555
556                 if ($kind == 'tgz') {
557                         $this->arc_kind = TARLIB_KIND_TGZ;
558                         $this->fp = gzopen($this->filename, 'rb');
559                 } else {
560                         $this->arc_kind = TARLIB_KIND_TAR;
561                         $this->fp =  fopen($this->filename, 'rb');
562                 }
563
564                 if ($this->fp === FALSE) {
565                         return FALSE;   // No such file
566                 } else {
567                         $this->status = TARLIB_STATUS_OPEN;
568                         rewind($this->fp);
569                         return TRUE;
570                 }
571         }
572
573         ////////////////////////////////////////////////////////////
574         // ´Ø¿ô  : »ØÄꤷ¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Ëtar¥Õ¥¡¥¤¥ë¤òŸ³«¤¹¤ë
575         // °ú¿ô  : Å¸³«¤¹¤ë¥Õ¥¡¥¤¥ë¥Ñ¥¿¡¼¥ó(Àµµ¬É½¸½)
576         // ÊÖ¤êÃÍ: Å¸³«¤·¤¿¥Õ¥¡¥¤¥ë̾¤Î°ìÍ÷
577         // Êä­  : ARAI¤µ¤ó¤Îattach¥×¥é¥°¥¤¥ó¥Ñ¥Ã¥Á¤ò»²¹Í¤Ë¤·¤Þ¤·¤¿
578         ////////////////////////////////////////////////////////////
579         function extract($pattern)
580         {
581                 if ($this->status != TARLIB_STATUS_OPEN) return ''; // Not opened
582                 
583                 $files = array();
584                 $longname = '';
585
586                 while(1) {
587                         $buff = fread($this->fp, TARLIB_HDR_LEN);
588                         if (strlen($buff) != TARLIB_HDR_LEN) break;
589
590                         // ¥Õ¥¡¥¤¥ë̾
591                         $name = '';
592                         if ($longname != '') {
593                                 $name     = $longname;  // LongLinkÂбþ
594                                 $longname = '';
595                         } else {
596                                 for ($i = 0; $i < TARLIB_HDR_NAME_LEN; $i++ ) {
597                                         if ($buff{$i + TARLIB_HDR_NAME_OFFSET} != "\0") {
598                                                 $name .= $buff{$i + TARLIB_HDR_NAME_OFFSET};
599                                         } else {
600                                                 break;
601                                         }
602                                 }
603                         }
604                         $name = trim($name);
605
606                         if ($name == '') break; // Å¸³«½ªÎ»
607
608                         // ¥Á¥§¥Ã¥¯¥µ¥à¤ò¼èÆÀ¤·¤Ä¤Ä¡¢¥Ö¥é¥ó¥¯¤ËÃÖ´¹¤·¤Æ¤¤¤¯
609                         $checksum = '';
610                         $chkblanks = TARLIB_DATA_CHKBLANKS;
611                         for ($i = 0; $i < TARLIB_HDR_CHKSUM_LEN; $i++ ) {
612                                 $checksum .= $buff{$i + TARLIB_HDR_CHKSUM_OFFSET};
613                                 $buff{$i + TARLIB_HDR_CHKSUM_OFFSET} = $chkblanks{$i};
614                         }
615                         list($checksum) = sscanf('0' . trim($checksum), '%i');
616
617                         // Compute checksum
618                         $sum = 0;
619                         for($i = 0; $i < TARLIB_BLK_LEN; $i++ ) {
620                                 $sum += 0xff & ord($buff{$i});
621                         }
622                         if ($sum != $checksum) break; // Error
623                                 
624                         // Size
625                         $size = '';
626                         for ($i = 0; $i < TARLIB_HDR_SIZE_LEN; $i++ ) {
627                                 $size .= $buff{$i + TARLIB_HDR_SIZE_OFFSET};
628                         }
629                         list($size) = sscanf('0' . trim($size), '%i');
630
631                         // ceil
632                         // ¥Ç¡¼¥¿¥Ö¥í¥Ã¥¯¤Ï512byte¤Ç¥Ñ¥Ç¥£¥ó¥°¤µ¤ì¤Æ¤¤¤ë
633                         $pdsz = ceil($size / TARLIB_BLK_LEN) * TARLIB_BLK_LEN;
634
635                         // ºÇ½ª¹¹¿·»þ¹ï
636                         $strmtime = '';
637                         for ($i = 0; $i < TARLIB_HDR_MTIME_LEN; $i++ ) {
638                                 $strmtime .= $buff{$i + TARLIB_HDR_MTIME_OFFSET};
639                         }
640                         list($mtime) = sscanf('0' . trim($strmtime), '%i');
641
642                         // ¥¿¥¤¥×¥Õ¥é¥°
643 //                       $type = $buff{TARLIB_HDR_TYPE_OFFSET};
644
645                         if ($name == TARLIB_DATA_LONGLINK) {
646                                 // LongLink
647                                 $buff     = fread($this->fp, $pdsz);
648                                 $longname = substr($buff, 0, $size);
649                         } else if (preg_match("/$pattern/", $name) ) {
650 //                      } else if ($type == 0 && preg_match("/$pattern/", $name) ) {
651                                 $buff = fread($this->fp, $pdsz);
652
653                                 // ´û¤ËƱ¤¸¥Õ¥¡¥¤¥ë¤¬¤¢¤ë¾ì¹ç¤Ï¾å½ñ¤­¤µ¤ì¤ë
654                                 $fpw = @fopen($name, 'wb');
655                                 if ($fpw !== FALSE) {
656                                         flock($fpw, LOCK_EX);
657                                         fwrite($fpw, $buff, $size);
658                                         @chmod($name, 0666);
659                                         @touch($name, $mtime);
660                                         flock($fpw, LOCK_UN);
661
662                                         fclose($fpw);
663                                         $files[] = $name;
664                                 }
665                         } else {
666                                 // ¥Õ¥¡¥¤¥ë¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë
667                                 @fseek($this->fp, $pdsz, SEEK_CUR);
668                         }
669                 }
670                 return $files;
671         }
672
673         ////////////////////////////////////////////////////////////
674         // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ë
675         // °ú¿ô  : ¤Ê¤·
676         // ÊÖ¤êÃÍ: ¤Ê¤·
677         ////////////////////////////////////////////////////////////
678         function close()
679         {
680                 if ($this->status == TARLIB_STATUS_CREATE) {
681                         // ¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ë
682                         if ($this->arc_kind == TARLIB_KIND_TGZ) {
683                                 // ¥Ð¥¤¥Ê¥ê¡¼¥¼¥í¤ò1024¥Ð¥¤¥È½ÐÎÏ
684                                 gzwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
685                                 gzwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
686                                 gzclose($this->fp);
687                         } else {
688                                 // ¥Ð¥¤¥Ê¥ê¡¼¥¼¥í¤ò1024¥Ð¥¤¥È½ÐÎÏ
689                                 fwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
690                                 fwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
691                                 fclose($this->fp);
692                         }
693                 } else if ($this->status == TARLIB_STATUS_OPEN) {
694                         if ($this->arc_kind == TARLIB_KIND_TGZ) {
695                                 gzclose($this->fp);
696                         } else {
697                                  fclose($this->fp);
698                         }
699                 }
700
701                 $this->status = TARLIB_STATUS_INIT;
702         }
703
704 }
705 ?>