OSDN Git Service

BugTrack2/122: tempnam() fails when open_basedir is specified in php.ini
[pukiwiki/pukiwiki.git] / plugin / dump.inc.php
1 <?php
2 // $Id: dump.inc.php,v 1.37 2006/01/12 01:01:35 teanan 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(realpath(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" id="_p_dump_tgz" value="tgz" checked="checked" />
228   <label for="_p_dump_tgz"> ¡Á.tar.gz ·Á¼°</label><br />
229   <input type="radio" name="pcmd" id="_p_dump_tar" value="tar" />
230   <label for="_p_dump_tar">¡Á.tar ·Á¼°</label>
231 </p>
232 <p><strong>¥Ð¥Ã¥¯¥¢¥Ã¥×¥Ç¥£¥ì¥¯¥È¥ê</strong>
233 <br />
234   <input type="checkbox" name="bk_wiki" id="_p_dump_d_wiki" checked="checked" />
235   <label for="_p_dump_d_wiki">wiki</label><br />
236   <input type="checkbox" name="bk_attach" id="_p_dump_d_attach" />
237   <label for="_p_dump_d_attach">attach</label><br />
238   <input type="checkbox" name="bk_backup" id="_p_dump_d_backup" />
239   <label for="_p_dump_d_backup">backup</label><br />
240 </p>
241 <p><strong>¥ª¥×¥·¥ç¥ó</strong>
242 <br />
243   <input type="checkbox" name="namedecode" id="_p_dump_namedecode" />
244   <label for="_p_dump_namedecode">¥¨¥ó¥³¡¼¥É¤µ¤ì¤Æ¤¤¤ë¥Ú¡¼¥¸Ì¾¤ò¥Ç¥£¥ì¥¯¥È¥ê³¬ÁؤĤ­¤Î¥Õ¥¡¥¤¥ë¤Ë¥Ç¥³¡¼¥É
245   (¢¨¥ê¥¹¥È¥¢¤Ë»È¤¦¤³¤È¤Ï¤Ç¤­¤Ê¤¯¤Ê¤ê¤Þ¤¹¡£¤Þ¤¿¡¢°ìÉô¤Îʸ»ú¤Ï '_' ¤ËÃÖ´¹¤µ¤ì¤Þ¤¹)</label><br />
246 </p>
247 <p><label for="_p_dump_adminpass_dump"><strong>´ÉÍý¼Ô¥Ñ¥¹¥ï¡¼¥É</strong></label>
248   <input type="password" name="pass" id="_p_dump_adminpass_dump" size="12" />
249   <input type="submit"   name="ok"   value="OK" />
250 </p>
251  </div>
252 </form>
253 EOD;
254
255         if(PLUGIN_DUMP_ALLOW_RESTORE) {
256                 $data .= <<<EOD
257 <h3>¥Ç¡¼¥¿¤Î¥ê¥¹¥È¥¢ (*.tar, *.tar.gz)</h3>
258 <form enctype="multipart/form-data" action="$script" method="post">
259  <div>
260   <input type="hidden" name="cmd"  value="dump" />
261   <input type="hidden" name="page" value="$defaultpage" />
262   <input type="hidden" name="act"  value="$act_up" />
263 <p><strong>[½ÅÍ×] Æ±¤¸Ì¾Á°¤Î¥Ç¡¼¥¿¥Õ¥¡¥¤¥ë¤Ï¾å½ñ¤­¤µ¤ì¤Þ¤¹¤Î¤Ç¡¢½½Ê¬¤´Ãí°Õ¤¯¤À¤µ¤¤¡£</strong></p>
264 <p><span class="small">
265 ¥¢¥Ã¥×¥í¡¼¥É²Äǽ¤ÊºÇÂç¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤Ï¡¢$maxsize KByte ¤Þ¤Ç¤Ç¤¹¡£<br />
266 </span>
267   <label for="_p_dump_upload_file">¥Õ¥¡¥¤¥ë:</label>
268   <input type="file" name="upload_file" id="_p_dump_upload_file" size="40" />
269 </p>
270 <p><label for="_p_dump_adminpass_restore"><strong>´ÉÍý¼Ô¥Ñ¥¹¥ï¡¼¥É</strong></label>
271   <input type="password" name="pass" id="_p_dump_adminpass_restore" size="12" />
272   <input type="submit"   name="ok"   value="OK" />
273 </p>
274  </div>
275 </form>
276 EOD;
277         }
278
279         return $data;
280 }
281
282 /////////////////////////////////////////////////
283 // tarlib: a class library for tar file creation and expansion
284
285 // Tar related definition
286 define('TARLIB_HDR_LEN',           512);        // ¥Ø¥Ã¥À¤ÎÂ礭¤µ
287 define('TARLIB_BLK_LEN',           512);        // Ã±°Ì¥Ö¥í¥Ã¥¯Ä¹¤µ
288 define('TARLIB_HDR_NAME_OFFSET',     0);        // ¥Õ¥¡¥¤¥ë̾¤Î¥ª¥Õ¥»¥Ã¥È
289 define('TARLIB_HDR_NAME_LEN',      100);        // ¥Õ¥¡¥¤¥ë̾¤ÎºÇÂ獵
290 define('TARLIB_HDR_MODE_OFFSET',   100);        // mode¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
291 define('TARLIB_HDR_UID_OFFSET',    108);        // uid¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
292 define('TARLIB_HDR_GID_OFFSET',    116);        // gid¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
293 define('TARLIB_HDR_SIZE_OFFSET',   124);        // ¥µ¥¤¥º¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
294 define('TARLIB_HDR_SIZE_LEN',       12);        // ¥µ¥¤¥º¤ÎŤµ
295 define('TARLIB_HDR_MTIME_OFFSET',  136);        // ºÇ½ª¹¹¿·»þ¹ï¤Î¥ª¥Õ¥»¥Ã¥È
296 define('TARLIB_HDR_MTIME_LEN',      12);        // ºÇ½ª¹¹¿·»þ¹ï¤ÎŤµ
297 define('TARLIB_HDR_CHKSUM_OFFSET', 148);        // ¥Á¥§¥Ã¥¯¥µ¥à¤Î¥ª¥Õ¥»¥Ã¥È
298 define('TARLIB_HDR_CHKSUM_LEN',      8);        // ¥Á¥§¥Ã¥¯¥µ¥à¤ÎŤµ
299 define('TARLIB_HDR_TYPE_OFFSET',   156);        // ¥Õ¥¡¥¤¥ë¥¿¥¤¥×¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
300
301 // Status
302 define('TARLIB_STATUS_INIT',    0);             // ½é´ü¾õÂÖ
303 define('TARLIB_STATUS_OPEN',   10);             // Æɤ߼è¤ê
304 define('TARLIB_STATUS_CREATE', 20);             // ½ñ¤­¹þ¤ß
305
306 define('TARLIB_DATA_MODE',      '100666 ');     // ¥Õ¥¡¥¤¥ë¥Ñ¡¼¥ß¥Ã¥·¥ç¥ó
307 define('TARLIB_DATA_UGID',      '000000 ');     // uid / gid
308 define('TARLIB_DATA_CHKBLANKS', '        ');
309
310 // GNU³ÈÄ¥»ÅÍÍ(¥í¥ó¥°¥Õ¥¡¥¤¥ë̾Âбþ)
311 define('TARLIB_DATA_LONGLINK', '././@LongLink');
312
313 // Type flag
314 define('TARLIB_HDR_FILE', '0');
315 define('TARLIB_HDR_LINK', 'L');
316
317 // Kind of the archive
318 define('TARLIB_KIND_TGZ', 0);
319 define('TARLIB_KIND_TAR', 1);
320
321 class tarlib
322 {
323         var $filename;
324         var $fp;
325         var $status;
326         var $arc_kind;
327         var $dummydata;
328
329         // ¥³¥ó¥¹¥È¥é¥¯¥¿
330         function tarlib() {
331                 $this->filename = '';
332                 $this->fp       = FALSE;
333                 $this->status   = TARLIB_STATUS_INIT;
334                 $this->arc_kind = TARLIB_KIND_TGZ;
335         }
336         
337         ////////////////////////////////////////////////////////////
338         // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë
339         // °ú¿ô  : tar¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë¥Ñ¥¹
340         // ÊÖ¤êÃÍ: TRUE .. À®¸ù , FALSE .. ¼ºÇÔ
341         ////////////////////////////////////////////////////////////
342         function create($tempdir, $kind = 'tgz')
343         {
344                 $tempnam = tempnam(realpath($tempdir), 'tarlib_create_');
345                 if ($tempnam === FALSE) return FALSE;
346
347                 if ($kind == 'tgz') {
348                         $this->arc_kind = TARLIB_KIND_TGZ;
349                         $this->fp       = gzopen($tempnam, 'wb');
350                 } else {
351                         $this->arc_kind = TARLIB_KIND_TAR;
352                         $this->fp       = @fopen($tempnam, 'wb');
353                 }
354
355                 if ($this->fp === FALSE) {
356                         @unlink($tempnam);
357                         return FALSE;
358                 } else {
359                         $this->filename  = $tempnam;
360                         $this->dummydata = join('', array_fill(0, TARLIB_BLK_LEN, "\0"));
361                         $this->status    = TARLIB_STATUS_CREATE;
362                         rewind($this->fp);
363                         return TRUE;
364                 }
365         }
366
367         ////////////////////////////////////////////////////////////
368         // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤òÄɲ乤ë
369         // °ú¿ô  : $dir    .. ¥Ç¥£¥ì¥¯¥È¥ê̾
370         //         $mask   .. Äɲ乤ë¥Õ¥¡¥¤¥ë(Àµµ¬É½¸½)
371         //         $decode .. ¥Ú¡¼¥¸Ì¾¤ÎÊÑ´¹¤ò¤¹¤ë¤«
372         // ÊÖ¤êÃÍ: ºîÀ®¤·¤¿¥Õ¥¡¥¤¥ë¿ô
373         ////////////////////////////////////////////////////////////
374         function add_dir($dir, $mask, $decode = FALSE)
375         {
376                 $retvalue = 0;
377                 
378                 if ($this->status != TARLIB_STATUS_CREATE)
379                         return ''; // File is not created
380
381                 unset($files);
382
383                 //  »ØÄꤵ¤ì¤¿¥Ñ¥¹¤Î¥Õ¥¡¥¤¥ë¤Î¥ê¥¹¥È¤ò¼èÆÀ¤¹¤ë
384                 $dp = @opendir($dir);
385                 if($dp === FALSE) {
386                         @unlink($this->filename);
387                         die_message($dir . ' is not found or not readable.');
388                 }
389
390                 while ($filename = readdir($dp)) {
391                         if (preg_match("/$mask/", $filename))
392                                 $files[] = $dir . $filename;
393                 }
394                 closedir($dp);
395                 
396                 sort($files);
397
398                 $matches = array();
399                 foreach($files as $name)
400                 {
401                         // Tar¤Ë³ÊǼ¤¹¤ë¥Õ¥¡¥¤¥ë̾¤òdecode
402                         if ($decode === FALSE) {
403                                 $filename = $name;
404                         } else {
405                                 $dirname  = dirname(trim($name)) . '/';
406                                 $filename = basename(trim($name));
407                                 if (preg_match("/^((?:[0-9A-F]{2})+)_((?:[0-9A-F]{2})+)/", $filename, $matches)) {
408                                         // attach¥Õ¥¡¥¤¥ë̾
409                                         $filename = decode($matches[1]) . '/' . decode($matches[2]);
410                                 } else {
411                                         $pattern = '^((?:[0-9A-F]{2})+)((\.txt|\.gz)*)$';
412                                         if (preg_match("/$pattern/", $filename, $matches)) {
413                                                 $filename = decode($matches[1]) . $matches[2];
414
415                                                 // ´í¤Ê¤¤¥³¡¼¥É¤ÏÃÖ´¹¤·¤Æ¤ª¤¯
416                                                 $filename = str_replace(':',  '_', $filename);
417                                                 $filename = str_replace('\\', '_', $filename);
418                                         }
419                                 }
420                                 $filename = $dirname . $filename;
421                                 // ¥Õ¥¡¥¤¥ë̾¤Îʸ»ú¥³¡¼¥É¤òÊÑ´¹
422                                 if (function_exists('mb_convert_encoding'))
423                                         $filename = mb_convert_encoding($filename, PLUGIN_DUMP_FILENAME_ENCORDING);
424                         }
425
426                         // ºÇ½ª¹¹¿·»þ¹ï
427                         $mtime = filemtime($name);
428
429                         // ¥Õ¥¡¥¤¥ë̾Ĺ¤Î¥Á¥§¥Ã¥¯
430                         if (strlen($filename) > TARLIB_HDR_NAME_LEN) {
431                                 // LongLinkÂбþ
432                                 $size = strlen($filename);
433                                 // LonkLink¥Ø¥Ã¥ÀÀ¸À®
434                                 $tar_data = $this->_make_header(TARLIB_DATA_LONGLINK, $size, $mtime, TARLIB_HDR_LINK);
435                                 // ¥Õ¥¡¥¤¥ë½ÐÎÏ
436                                 $this->_write_data(join('', $tar_data), $filename, $size);
437                         }
438
439                         // ¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤ò¼èÆÀ
440                         $size = filesize($name);
441                         if ($size === FALSE) {
442                                 @unlink($this->filename);
443                                 die_message($name . ' is not found or not readable.');
444                         }
445
446                         // ¥Ø¥Ã¥ÀÀ¸À®
447                         $tar_data = $this->_make_header($filename, $size, $mtime, TARLIB_HDR_FILE);
448
449                         // ¥Õ¥¡¥¤¥ë¥Ç¡¼¥¿¤Î¼èÆÀ
450                         $fpr = @fopen($name , 'rb');
451                         flock($fpr, LOCK_SH);
452                         $data = fread($fpr, $size);
453                         flock($fpr, LOCK_UN);
454                         fclose( $fpr );
455
456                         // ¥Õ¥¡¥¤¥ë½ÐÎÏ
457                         $this->_write_data(join('', $tar_data), $data, $size);
458                         ++$retvalue;
459                 }
460                 return $retvalue;
461         }
462         
463         ////////////////////////////////////////////////////////////
464         // ´Ø¿ô  : tar¤Î¥Ø¥Ã¥À¾ðÊó¤òÀ¸À®¤¹¤ë (add)
465         // °ú¿ô  : $filename .. ¥Õ¥¡¥¤¥ë̾
466         //         $size     .. ¥Ç¡¼¥¿¥µ¥¤¥º
467         //         $mtime    .. ºÇ½ª¹¹¿·Æü
468         //         $typeflag .. TypeFlag (file/link)
469         // Ìá¤êÃÍ: tar¥Ø¥Ã¥À¾ðÊó
470         ////////////////////////////////////////////////////////////
471         function _make_header($filename, $size, $mtime, $typeflag)
472         {
473                 $tar_data = array_fill(0, TARLIB_HDR_LEN, "\0");
474                 
475                 // ¥Õ¥¡¥¤¥ë̾¤òÊݸ
476                 for($i = 0; $i < strlen($filename); $i++ ) {
477                         if ($i < TARLIB_HDR_NAME_LEN) {
478                                 $tar_data[$i + TARLIB_HDR_NAME_OFFSET] = $filename{$i};
479                         } else {
480                                 break;  // ¥Õ¥¡¥¤¥ë̾¤¬Ä¹¤¹¤®
481                         }
482                 }
483
484                 // mode
485                 $modeid = TARLIB_DATA_MODE;
486                 for($i = 0; $i < strlen($modeid); $i++ ) {
487                         $tar_data[$i + TARLIB_HDR_MODE_OFFSET] = $modeid{$i};
488                 }
489
490                 // uid / gid
491                 $ugid = TARLIB_DATA_UGID;
492                 for($i = 0; $i < strlen($ugid); $i++ ) {
493                         $tar_data[$i + TARLIB_HDR_UID_OFFSET] = $ugid{$i};
494                         $tar_data[$i + TARLIB_HDR_GID_OFFSET] = $ugid{$i};
495                 }
496
497                 // ¥µ¥¤¥º
498                 $strsize = sprintf('%11o', $size);
499                 for($i = 0; $i < strlen($strsize); $i++ ) {
500                         $tar_data[$i + TARLIB_HDR_SIZE_OFFSET] = $strsize{$i};
501                 }
502
503                 // ºÇ½ª¹¹¿·»þ¹ï
504                 $strmtime = sprintf('%o', $mtime);
505                 for($i = 0; $i < strlen($strmtime); $i++ ) {
506                         $tar_data[$i + TARLIB_HDR_MTIME_OFFSET] = $strmtime{$i};
507                 }
508
509                 // ¥Á¥§¥Ã¥¯¥µ¥à·×»»ÍѤΥ֥é¥ó¥¯¤òÀßÄê
510                 $chkblanks = TARLIB_DATA_CHKBLANKS;
511                 for($i = 0; $i < strlen($chkblanks); $i++ ) {
512                         $tar_data[$i + TARLIB_HDR_CHKSUM_OFFSET] = $chkblanks{$i};
513                 }
514
515                 // ¥¿¥¤¥×¥Õ¥é¥°
516                 $tar_data[TARLIB_HDR_TYPE_OFFSET] = $typeflag;
517
518                 // ¥Á¥§¥Ã¥¯¥µ¥à¤Î·×»»
519                 $sum = 0;
520                 for($i = 0; $i < TARLIB_BLK_LEN; $i++ ) {
521                         $sum += 0xff & ord($tar_data[$i]);
522                 }
523                 $strchksum = sprintf('%7o',$sum);
524                 for($i = 0; $i < strlen($strchksum); $i++ ) {
525                         $tar_data[$i + TARLIB_HDR_CHKSUM_OFFSET] = $strchksum{$i};
526                 }
527
528                 return $tar_data;
529         }
530         
531         ////////////////////////////////////////////////////////////
532         // ´Ø¿ô  : tar¥Ç¡¼¥¿¤Î¥Õ¥¡¥¤¥ë½ÐÎÏ (add)
533         // °ú¿ô  : $header .. tar¥Ø¥Ã¥À¾ðÊó
534         //         $body   .. tar¥Ç¡¼¥¿
535         //         $size   .. ¥Ç¡¼¥¿¥µ¥¤¥º
536         // Ìá¤êÃÍ: ¤Ê¤·
537         ////////////////////////////////////////////////////////////
538         function _write_data($header, $body, $size)
539         {
540                 $fixsize  = ceil($size / TARLIB_BLK_LEN) * TARLIB_BLK_LEN - $size;
541
542                 if ($this->arc_kind == TARLIB_KIND_TGZ) {
543                         gzwrite($this->fp, $header, TARLIB_HDR_LEN);    // Header
544                         gzwrite($this->fp, $body, $size);               // Body
545                         gzwrite($this->fp, $this->dummydata, $fixsize); // Padding
546                 } else {
547                          fwrite($this->fp, $header, TARLIB_HDR_LEN);    // Header
548                          fwrite($this->fp, $body, $size);               // Body
549                          fwrite($this->fp, $this->dummydata, $fixsize); // Padding
550                 }
551         }
552
553         ////////////////////////////////////////////////////////////
554         // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤ò³«¤¯
555         // °ú¿ô  : tar¥Õ¥¡¥¤¥ë̾
556         // ÊÖ¤êÃÍ: TRUE .. À®¸ù , FALSE .. ¼ºÇÔ
557         ////////////////////////////////////////////////////////////
558         function open($name = '', $kind = 'tgz')
559         {
560                 if (! PLUGIN_DUMP_ALLOW_RESTORE) return FALSE; // Not allowed
561
562                 if ($name != '') $this->filename = $name;
563
564                 if ($kind == 'tgz') {
565                         $this->arc_kind = TARLIB_KIND_TGZ;
566                         $this->fp = gzopen($this->filename, 'rb');
567                 } else {
568                         $this->arc_kind = TARLIB_KIND_TAR;
569                         $this->fp =  fopen($this->filename, 'rb');
570                 }
571
572                 if ($this->fp === FALSE) {
573                         return FALSE;   // No such file
574                 } else {
575                         $this->status = TARLIB_STATUS_OPEN;
576                         rewind($this->fp);
577                         return TRUE;
578                 }
579         }
580
581         ////////////////////////////////////////////////////////////
582         // ´Ø¿ô  : »ØÄꤷ¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Ëtar¥Õ¥¡¥¤¥ë¤òŸ³«¤¹¤ë
583         // °ú¿ô  : Å¸³«¤¹¤ë¥Õ¥¡¥¤¥ë¥Ñ¥¿¡¼¥ó(Àµµ¬É½¸½)
584         // ÊÖ¤êÃÍ: Å¸³«¤·¤¿¥Õ¥¡¥¤¥ë̾¤Î°ìÍ÷
585         // Êä­  : ARAI¤µ¤ó¤Îattach¥×¥é¥°¥¤¥ó¥Ñ¥Ã¥Á¤ò»²¹Í¤Ë¤·¤Þ¤·¤¿
586         ////////////////////////////////////////////////////////////
587         function extract($pattern)
588         {
589                 if ($this->status != TARLIB_STATUS_OPEN) return ''; // Not opened
590                 
591                 $files = array();
592                 $longname = '';
593
594                 while(1) {
595                         $buff = fread($this->fp, TARLIB_HDR_LEN);
596                         if (strlen($buff) != TARLIB_HDR_LEN) break;
597
598                         // ¥Õ¥¡¥¤¥ë̾
599                         $name = '';
600                         if ($longname != '') {
601                                 $name     = $longname;  // LongLinkÂбþ
602                                 $longname = '';
603                         } else {
604                                 for ($i = 0; $i < TARLIB_HDR_NAME_LEN; $i++ ) {
605                                         if ($buff{$i + TARLIB_HDR_NAME_OFFSET} != "\0") {
606                                                 $name .= $buff{$i + TARLIB_HDR_NAME_OFFSET};
607                                         } else {
608                                                 break;
609                                         }
610                                 }
611                         }
612                         $name = trim($name);
613
614                         if ($name == '') break; // Å¸³«½ªÎ»
615
616                         // ¥Á¥§¥Ã¥¯¥µ¥à¤ò¼èÆÀ¤·¤Ä¤Ä¡¢¥Ö¥é¥ó¥¯¤ËÃÖ´¹¤·¤Æ¤¤¤¯
617                         $checksum = '';
618                         $chkblanks = TARLIB_DATA_CHKBLANKS;
619                         for ($i = 0; $i < TARLIB_HDR_CHKSUM_LEN; $i++ ) {
620                                 $checksum .= $buff{$i + TARLIB_HDR_CHKSUM_OFFSET};
621                                 $buff{$i + TARLIB_HDR_CHKSUM_OFFSET} = $chkblanks{$i};
622                         }
623                         list($checksum) = sscanf('0' . trim($checksum), '%i');
624
625                         // Compute checksum
626                         $sum = 0;
627                         for($i = 0; $i < TARLIB_BLK_LEN; $i++ ) {
628                                 $sum += 0xff & ord($buff{$i});
629                         }
630                         if ($sum != $checksum) break; // Error
631                                 
632                         // Size
633                         $size = '';
634                         for ($i = 0; $i < TARLIB_HDR_SIZE_LEN; $i++ ) {
635                                 $size .= $buff{$i + TARLIB_HDR_SIZE_OFFSET};
636                         }
637                         list($size) = sscanf('0' . trim($size), '%i');
638
639                         // ceil
640                         // ¥Ç¡¼¥¿¥Ö¥í¥Ã¥¯¤Ï512byte¤Ç¥Ñ¥Ç¥£¥ó¥°¤µ¤ì¤Æ¤¤¤ë
641                         $pdsz = ceil($size / TARLIB_BLK_LEN) * TARLIB_BLK_LEN;
642
643                         // ºÇ½ª¹¹¿·»þ¹ï
644                         $strmtime = '';
645                         for ($i = 0; $i < TARLIB_HDR_MTIME_LEN; $i++ ) {
646                                 $strmtime .= $buff{$i + TARLIB_HDR_MTIME_OFFSET};
647                         }
648                         list($mtime) = sscanf('0' . trim($strmtime), '%i');
649
650                         // ¥¿¥¤¥×¥Õ¥é¥°
651 //                       $type = $buff{TARLIB_HDR_TYPE_OFFSET};
652
653                         if ($name == TARLIB_DATA_LONGLINK) {
654                                 // LongLink
655                                 $buff     = fread($this->fp, $pdsz);
656                                 $longname = substr($buff, 0, $size);
657                         } else if (preg_match("/$pattern/", $name) ) {
658 //                      } else if ($type == 0 && preg_match("/$pattern/", $name) ) {
659                                 $buff = fread($this->fp, $pdsz);
660
661                                 // ´û¤ËƱ¤¸¥Õ¥¡¥¤¥ë¤¬¤¢¤ë¾ì¹ç¤Ï¾å½ñ¤­¤µ¤ì¤ë
662                                 $fpw = @fopen($name, 'wb');
663                                 if ($fpw !== FALSE) {
664                                         flock($fpw, LOCK_EX);
665                                         fwrite($fpw, $buff, $size);
666                                         @chmod($name, 0666);
667                                         @touch($name, $mtime);
668                                         flock($fpw, LOCK_UN);
669
670                                         fclose($fpw);
671                                         $files[] = $name;
672                                 }
673                         } else {
674                                 // ¥Õ¥¡¥¤¥ë¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë
675                                 @fseek($this->fp, $pdsz, SEEK_CUR);
676                         }
677                 }
678                 return $files;
679         }
680
681         ////////////////////////////////////////////////////////////
682         // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ë
683         // °ú¿ô  : ¤Ê¤·
684         // ÊÖ¤êÃÍ: ¤Ê¤·
685         ////////////////////////////////////////////////////////////
686         function close()
687         {
688                 if ($this->status == TARLIB_STATUS_CREATE) {
689                         // ¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ë
690                         if ($this->arc_kind == TARLIB_KIND_TGZ) {
691                                 // ¥Ð¥¤¥Ê¥ê¡¼¥¼¥í¤ò1024¥Ð¥¤¥È½ÐÎÏ
692                                 gzwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
693                                 gzwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
694                                 gzclose($this->fp);
695                         } else {
696                                 // ¥Ð¥¤¥Ê¥ê¡¼¥¼¥í¤ò1024¥Ð¥¤¥È½ÐÎÏ
697                                 fwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
698                                 fwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
699                                 fclose($this->fp);
700                         }
701                 } else if ($this->status == TARLIB_STATUS_OPEN) {
702                         if ($this->arc_kind == TARLIB_KIND_TGZ) {
703                                 gzclose($this->fp);
704                         } else {
705                                  fclose($this->fp);
706                         }
707                 }
708
709                 $this->status = TARLIB_STATUS_INIT;
710         }
711
712 }
713 ?>