OSDN Git Service

Added function pkwk_headers_sent() to care header()
[pukiwiki/pukiwiki.git] / plugin / dump.inc.php
index 22ef8f3..f0af2ea 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /////////////////////////////////////////////////
-// $Id: dump.inc.php,v 1.12 2004/09/26 11:30:48 henoheno Exp $
+// $Id: dump.inc.php,v 1.32 2004/12/02 11:34:25 henoheno Exp $
 // Originated as tarfile.inc.php by teanan / Interfair Laboratory 2004.
 
 // [¹¹¿·ÍúÎò]
 // ¡¦¥ê¥¹¥È¥¢»þ¥Õ¥¡¥¤¥ë¤Î¹¹¿·»þ¹ï¤ò¸µ¤ËÌ᤹¤è¤¦¤Ë½¤Àµ
 
 /////////////////////////////////////////////////
-// User define
+// User defines
 
-// ¥Ú¡¼¥¸Ì¾¤ò¥Ç¥£¥ì¥¯¥È¥ê¹½Â¤¤ËÊÑ´¹¤¹¤ëºÝ¤ÎÆüËܸì¤Îʸ»ú¥³¡¼¥É
+// Allow using resture function
+define('PLUGIN_DUMP_ALLOW_RESTORE', FALSE); // FALSE, TRUE
+
+// ¥Ú¡¼¥¸Ì¾¤ò¥Ç¥£¥ì¥¯¥È¥ê¹½Â¤¤ËÊÑ´¹¤¹¤ëºÝ¤Îʸ»ú¥³¡¼¥É (for mbstring)
 define('PLUGIN_DUMP_FILENAME_ENCORDING', 'SJIS');
 
 // ºÇÂ祢¥Ã¥×¥í¡¼¥É¥µ¥¤¥º
 define('PLUGIN_DUMP_MAX_FILESIZE', 1024); // Kbyte
 
 /////////////////////////////////////////////////
+// Internal defines
 
 // Action
 define('PLUGIN_DUMP_DUMP',    'dump');    // Dump & download
 define('PLUGIN_DUMP_RESTORE', 'restore'); // Upload & restore
 
-// Suffixes
-define('PLUGIN_DUMP_SFX_TAR' , '.tar');
-define('PLUGIN_DUMP_SFX_GZIP', '.tar.gz');
+global $_STORAGE;
+
+// DATA_DIR (wiki/*.txt)
+$_STORAGE['DATA_DIR']['add_filter']     = '^[0-9A-F]+\.txt';
+$_STORAGE['DATA_DIR']['extract_filter'] = '^' . preg_quote(DATA_DIR, '/')   . '((?:[0-9A-F])+)(\.txt){0,1}';
+
+// UPLOAD_DIR (attach/*)
+$_STORAGE['UPLOAD_DIR']['add_filter']     = '^[0-9A-F_]+';
+$_STORAGE['UPLOAD_DIR']['extract_filter'] = '^' . preg_quote(UPLOAD_DIR, '/') . '((?:[0-9A-F]{2})+)_((?:[0-9A-F])+)';
 
-define('ARCFILE_TAR_GZ', 0);
-define('ARCFILE_TAR',  1);
+// BACKUP_DIR (backup/*.gz)
+$_STORAGE['BACKUP_DIR']['add_filter']     = '^[0-9A-F]+\.gz';
+$_STORAGE['BACKUP_DIR']['extract_filter'] =  '^' . preg_quote(BACKUP_DIR, '/') . '((?:[0-9A-F])+)(\.gz){0,1}';
 
 
 /////////////////////////////////////////////////
@@ -47,13 +58,15 @@ function plugin_dump_action()
 {
        global $vars;
 
-       $pass = isset($vars['pass']) ? $vars['pass'] : NULL;
-       $act  = isset($vars['act'])  ? $vars['act']  : NULL;
+       $pass = isset($_POST['pass']) ? $_POST['pass'] : NULL;
+       $act  = isset($vars['act'])   ? $vars['act']   : NULL;
 
        $body = '';
 
        if ($pass !== NULL) {
-               if (pkwk_login($pass) && ($act !== NULL) ) {
+               if (! pkwk_login($pass)) {
+                       $body = "<p><strong>¥Ñ¥¹¥ï¡¼¥É¤¬°ã¤¤¤Þ¤¹¡£</strong></p>\n";
+               } else {
                        switch($act){
                        case PLUGIN_DUMP_DUMP:
                                $body = plugin_dump_download();
@@ -61,32 +74,38 @@ function plugin_dump_action()
                        case PLUGIN_DUMP_RESTORE:
                                $retcode = plugin_dump_upload();
                                if ($retcode['code'] == TRUE) {
-                                       // Àµ¾ï½ªÎ»
                                        $msg = '¥¢¥Ã¥×¥í¡¼¥É¤¬´°Î»¤·¤Þ¤·¤¿';
-                                       $body .= $retcode['msg'];
-                                       return array('msg' => $msg, 'body' => $body);
+                               } else {
+                                       $msg = '¥¢¥Ã¥×¥í¡¼¥É¤Ë¼ºÇÔ¤·¤Þ¤·¤¿';
                                }
+                               $body .= $retcode['msg'];
+                               return array('msg' => $msg, 'body' => $body);
                                break;
                        }
-               } else {
-                       $body = ($pass === NULL) ? '' : "<p><strong>¥Ñ¥¹¥ï¡¼¥É¤¬°ã¤¤¤Þ¤¹¡£</strong></p>\n";
                }
        }
 
        // ÆþÎÏ¥Õ¥©¡¼¥à¤òɽ¼¨
        $body .= plugin_dump_disp_form();
-       
-       return array('msg' => 'dump & restore', 'body' => $body);
+
+       $msg = '';
+       if (PLUGIN_DUMP_ALLOW_RESTORE) {
+               $msg = 'dump & restore';
+       } else {
+               $msg = 'dump';
+       }
+
+       return array('msg' => $msg, 'body' => $body);
 }
 
 /////////////////////////////////////////////////
 // ¥Õ¥¡¥¤¥ë¤Î¥À¥¦¥ó¥í¡¼¥É
 function plugin_dump_download()
 {
-       global $vars;
+       global $vars, $_STORAGE;
 
        // ¥¢¡¼¥«¥¤¥Ö¤Î¼ïÎà
-       $arc_kind = ($vars['pcmd'] == 'tar') ? ARCFILE_TAR : ARCFILE_TAR_GZ;
+       $arc_kind = ($vars['pcmd'] == 'tar') ? 'tar' : 'tgz';
 
        // ¥Ú¡¼¥¸Ì¾¤ËÊÑ´¹¤¹¤ë
        $namedecode = isset($vars['namedecode']) ? TRUE : FALSE;
@@ -96,30 +115,25 @@ function plugin_dump_download()
        $bk_attach = isset($vars['bk_attach']) ? TRUE : FALSE;
        $bk_backup = isset($vars['bk_backup']) ? TRUE : FALSE;
 
+       $filecount = 0;
        $tar = new tarlib();
-
-       // ¥Õ¥¡¥¤¥ë¤òÀ¸À®¤¹¤ë
-       if ($tar->create(CACHE_DIR, $arc_kind))
-       {
-               $filecount = 0;         // ¥Õ¥¡¥¤¥ë¿ô
-               if ($bk_wiki)   $filecount .= $tar->add(DATA_DIR,   '^[0-9A-F]+\.txt', $namedecode);
-               if ($bk_attach) $filecount .= $tar->add(UPLOAD_DIR, '^[0-9A-F_]+',     $namedecode);
-               if ($bk_backup) $filecount .= $tar->add(BACKUP_DIR, '^[0-9A-F]+\.gz',  $namedecode);
-               $tar->close();
-
-               if ($filecount > 0) {
-                       // ¥À¥¦¥ó¥í¡¼¥É
-                       download_tarfile($tar->filename, $arc_kind);
-                       @unlink($tar->filename);
-                       exit;   // Àµ¾ï½ªÎ»
-               } else {
-                       @unlink($tar->filename);
-                       return '<p><strong>¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£</strong></p>';
-               }
-       }
-       else
-       {
+       $tar->create(CACHE_DIR, $arc_kind) or
                die_message('¥Æ¥ó¥Ý¥é¥ê¥Õ¥¡¥¤¥ë¤ÎÀ¸À®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿¡£');
+
+       if ($bk_wiki)   $filecount += $tar->add_dir(DATA_DIR,   $_STORAGE['DATA_DIR']['add_filter'],   $namedecode);
+       if ($bk_attach) $filecount += $tar->add_dir(UPLOAD_DIR, $_STORAGE['UPLOAD_DIR']['add_filter'], $namedecode);
+       if ($bk_backup) $filecount += $tar->add_dir(BACKUP_DIR, $_STORAGE['BACKUP_DIR']['add_filter'], $namedecode);
+
+       $tar->close();
+
+       if ($filecount === 0) {
+               @unlink($tar->filename);
+               return '<p><strong>¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£</strong></p>';
+       } else {
+               // ¥À¥¦¥ó¥í¡¼¥É
+               download_tarfile($tar->filename, $arc_kind);
+               @unlink($tar->filename);
+               exit;   // Àµ¾ï½ªÎ»
        }
 }
 
@@ -127,96 +141,77 @@ function plugin_dump_download()
 // ¥Õ¥¡¥¤¥ë¤Î¥¢¥Ã¥×¥í¡¼¥É
 function plugin_dump_upload()
 {
-       global $vars;
+       global $vars, $_STORAGE;
 
-       $code = FALSE;
-       $msg  = '';
+       if (! PLUGIN_DUMP_ALLOW_RESTORE)
+               return array('code' => FALSE , 'msg' => 'Restoring function is not allowed');
 
        $filename = $_FILES['upload_file']['name'];
-       $matches = array();
+       $matches  = array();
        $arc_kind = FALSE;
        if(! preg_match('/(\.tar|\.tar.gz|\.tgz)$/', $filename, $matches)){
-               die_message("Invalid file suffix");
+               die_message('Invalid file suffix');
        } else { 
                $matches[1] = strtolower($matches[1]);
                switch ($matches[1]) {
-               case '.tar':    $arc_kind = ARCFILE_TAR;  break;
-               case '.tgz':    $arc_kind = ARCFILE_TAR_GZ; break;
-               case '.tar.gz': $arc_kind = ARCFILE_TAR_GZ; break;
-               default: die_message("Invalid file suffix: " . $matches[1]);
-               }
+               case '.tar':    $arc_kind = 'tar'; break;
+               case '.tgz':    $arc_kind = 'tar'; break;
+               case '.tar.gz': $arc_kind = 'tgz'; break;
+               default: die_message('Invalid file suffix: ' . $matches[1]); }
        }
 
        if ($_FILES['upload_file']['size'] >  PLUGIN_DUMP_MAX_FILESIZE * 1024)
-               die_message("Max file size exceeded: " . PLUGIN_DUMP_MAX_FILESIZE . "KB");
-
-       // ¥¢¥Ã¥×¥í¡¼¥É¥Õ¥¡¥¤¥ë
-       $uploadfile = tempnam(CACHE_DIR, 'upload' );
-       if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $uploadfile))
-       {
-               // tar¥Õ¥¡¥¤¥ë¤òŸ³«¤¹¤ë
-               $tar = new tarlib();
-               if ($tar->open($uploadfile, $arc_kind))
-               {
-                       // DATA_DIR (wiki/*.txt)
-                       $quote_wiki  = preg_quote(DATA_DIR, '/');
-                       $quote_wiki .= '((?:[0-9A-F])+)(\.txt){0,1}';
+               die_message('Max file size exceeded: ' . PLUGIN_DUMP_MAX_FILESIZE . 'KB');
 
-                       // UPLOAD_DIR (attach/*)
-                       $quote_attach  = preg_quote(UPLOAD_DIR,'/');
-                       $quote_attach .= '((?:[0-9A-F]{2})+)_((?:[0-9A-F])+)';
+       // Create a temporary tar file
+       $uploadfile = tempnam(CACHE_DIR, 'tarlib_uploaded_');
+       $tar = new tarlib();
+       if(! move_uploaded_file($_FILES['upload_file']['tmp_name'], $uploadfile) ||
+          ! $tar->open($uploadfile, $arc_kind)) {
+               @unlink($uploadfile);
+               die_message('¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£');
+       }
 
-                       $pattern = "((^$quote_wiki)|(^$quote_attach))";
-       
-                       $files = $tar->extract($pattern);
-                       if (! empty($files)) {
-                               $msg  = '<p><strong>Ÿ³«¤·¤¿¥Õ¥¡¥¤¥ë°ìÍ÷</strong><ul>';
-                               foreach($files as $name) {
-                                       $msg .= "<li>$name</li>\n";
-                               }
-                               $msg .= '</ul></p>';
-                               $code = TRUE;
-                       } else {
-                               $msg = '<p>Ÿ³«¤Ç¤­¤ë¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£</p>';
-                               $code = FALSE;
-                       }
-                       $tar->close();
-               }
-               else
-               {
-                       $msg = '<p>¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£</p>';
-                       $code = FALSE;
-               }
-               // ½èÍý¤¬½ªÎ»¤·¤¿¤é¥¢¥Ã¥×¥í¡¼¥É¤·¤¿¥Õ¥¡¥¤¥ë¤Ïºï½ü¤¹¤ë
+       $pattern = "(({$_STORAGE['DATA_DIR']['extract_filter']})|" .
+                   "({$_STORAGE['UPLOAD_DIR']['extract_filter']})|" .
+                   "({$_STORAGE['BACKUP_DIR']['extract_filter']}))";
+       $files = $tar->extract($pattern);
+       if (empty($files)) {
                @unlink($uploadfile);
+               return array('code' => FALSE, 'msg' => '<p>Ÿ³«¤Ç¤­¤ë¥Õ¥¡¥¤¥ë¤¬¤¢¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£</p>');
        }
-       else
-       {
-               die_message('¥Õ¥¡¥¤¥ë¤¬¤ß¤Ä¤«¤ê¤Þ¤»¤ó¤Ç¤·¤¿¡£');
+
+       $msg  = '<p><strong>Ÿ³«¤·¤¿¥Õ¥¡¥¤¥ë°ìÍ÷</strong><ul>';
+       foreach($files as $name) {
+               $msg .= "<li>$name</li>\n";
        }
+       $msg .= '</ul></p>';
+
+       $tar->close();
+       @unlink($uploadfile);
 
-       return array('code' => $code , 'msg' => $msg);
+       return array('code' => TRUE, 'msg' => $msg);
 }
 
 /////////////////////////////////////////////////
 // tar¥Õ¥¡¥¤¥ë¤Î¥À¥¦¥ó¥í¡¼¥É
-function download_tarfile($name, $arc_kind)
+function download_tarfile($tempnam, $arc_kind)
 {
-       // ¥Õ¥¡¥¤¥ë̾
+       $size = filesize($tempnam);
+
        $filename = strftime('tar%Y%m%d', time());
-       if ($arc_kind == ARCFILE_TAR_GZ) {
-               $filename .= PLUGIN_DUMP_SFX_GZIP;
+       if ($arc_kind == 'tgz') {
+               $filename .= '.tar.gz';
        } else {
-               $filename .= PLUGIN_DUMP_SFX_TAR;
+               $filename .= '.tar';
        }
 
-       $size = filesize($name);
-
+       pkwk_headers_sent();
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: ' . $size);
        header('Content-Type: application/octet-stream');
        header('Pragma: no-cache');
-       @readfile($name);
+       @readfile($tempnam);
 }
 
 /////////////////////////////////////////////////
@@ -260,7 +255,10 @@ function plugin_dump_disp_form()
 </p>
  </div>
 </form>
+EOD;
 
+       if(PLUGIN_DUMP_ALLOW_RESTORE) {
+               $data .= <<<EOD
 <h3>¥Ç¡¼¥¿¤Î¥ê¥¹¥È¥¢ (*.tar, *.tar.gz)</h3>
 <form enctype="multipart/form-data" action="$script" method="post">
  <div>
@@ -280,12 +278,13 @@ function plugin_dump_disp_form()
  </div>
 </form>
 EOD;
+       }
 
        return $data;
 }
 
 /////////////////////////////////////////////////
-// tarlib: library for tar file creation and expansion
+// tarlib: a class library for tar file creation and expansion
 
 // Tar related definition
 define('TARLIB_HDR_LEN',           512);       // ¥Ø¥Ã¥À¤ÎÂ礭¤µ
@@ -308,15 +307,21 @@ define('TARLIB_STATUS_INIT',    0);               // 
 define('TARLIB_STATUS_OPEN',   10);            // Æɤ߼è¤ê
 define('TARLIB_STATUS_CREATE', 20);            // ½ñ¤­¹þ¤ß
 
-define('TARLIB_DATA_MODE',   '100666 ');       // ¥Õ¥¡¥¤¥ë¥Ñ¡¼¥ß¥Ã¥·¥ç¥ó
-define('TARLIB_DATA_UGID',   '000000 ');       // uid / gid
+define('TARLIB_DATA_MODE',      '100666 ');    // ¥Õ¥¡¥¤¥ë¥Ñ¡¼¥ß¥Ã¥·¥ç¥ó
+define('TARLIB_DATA_UGID',      '000000 ');    // uid / gid
 define('TARLIB_DATA_CHKBLANKS', '        ');
 
 // GNU³ÈÄ¥»ÅÍÍ(¥í¥ó¥°¥Õ¥¡¥¤¥ë̾Âбþ)
 define('TARLIB_DATA_LONGLINK', '././@LongLink');
+
+// Type flag
 define('TARLIB_HDR_FILE', '0');
 define('TARLIB_HDR_LINK', 'L');
 
+// Kind of the archive
+define('TARLIB_KIND_TGZ', 0);
+define('TARLIB_KIND_TAR', 1);
+
 class tarlib
 {
        var $filename;
@@ -326,233 +331,66 @@ class tarlib
        var $dummydata;
 
        // ¥³¥ó¥¹¥È¥é¥¯¥¿
-       function tarlib( $name = '' ) {
-               $this->filename = $name;
+       function tarlib() {
+               $this->filename = '';
                $this->fp       = FALSE;
                $this->status   = TARLIB_STATUS_INIT;
-               $this->arc_kind = ARCFILE_TAR_GZ;
+               $this->arc_kind = TARLIB_KIND_TGZ;
        }
        
        ////////////////////////////////////////////////////////////
-       //
-       // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤ò³«¤¯
-       // °ú¿ô  : tar¥Õ¥¡¥¤¥ë̾
+       // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë
+       // °ú¿ô  : tar¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë¥Ñ¥¹
        // ÊÖ¤êÃÍ: TRUE .. À®¸ù , FALSE .. ¼ºÇÔ
-       //
        ////////////////////////////////////////////////////////////
-       function open($name = '', $kind = ARCFILE_TAR_GZ)
+       function create($tempdir, $kind = 'tgz')
        {
-               if ($name != '') $this->filename = $name;
+               $tempnam = tempnam($tempdir, 'tarlib_create_');
+               if ($tempnam === FALSE) return FALSE;
 
-               if ($kind == ARCFILE_TAR_GZ) {
-                       $this->arc_kind = ARCFILE_TAR_GZ;
-                       $this->fp = gzopen($this->filename, 'rb');
+               if ($kind == 'tgz') {
+                       $this->arc_kind = TARLIB_KIND_TGZ;
+                       $this->fp       = gzopen($tempnam, 'wb');
                } else {
-                       $this->arc_kind = ARCFILE_TAR;
-                       $this->fp =  fopen($this->filename, 'rb');
+                       $this->arc_kind = TARLIB_KIND_TAR;
+                       $this->fp       = @fopen($tempnam, 'wb');
                }
 
                if ($this->fp === FALSE) {
-                       return FALSE;   // No such file
+                       @unlink($tempnam);
+                       return FALSE;
                } else {
-                       $this->status = TARLIB_STATUS_OPEN;
+                       $this->filename  = $tempnam;
+                       $this->dummydata = join('', array_fill(0, TARLIB_BLK_LEN, "\0"));
+                       $this->status    = TARLIB_STATUS_CREATE;
                        rewind($this->fp);
                        return TRUE;
                }
        }
 
        ////////////////////////////////////////////////////////////
-       //
-       // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë
-       // °ú¿ô  : tar¥Õ¥¡¥¤¥ë¤òºîÀ®¤¹¤ë¥Ñ¥¹
-       // ÊÖ¤êÃÍ: TRUE .. À®¸ù , FALSE .. ¼ºÇÔ
-       //
-       ////////////////////////////////////////////////////////////
-       function create($odir, $kind = ARCFILE_TAR_GZ)
-       {
-               $tname = tempnam($odir, 'tar');
-
-               if ($kind == ARCFILE_TAR_GZ) {
-                       $this->arc_kind = ARCFILE_TAR_GZ;
-                       $this->fp = gzopen($tname, 'wb');
-               } else {
-                       $this->arc_kind = ARCFILE_TAR;
-                       $this->fp = @fopen($tname, 'wb');
-               }
-               if ($this->fp === FALSE) return FALSE;  // ºîÀ®¼ºÇÔ
-
-               // ºîÀ®¤ËÀ®¸ù¤·¤¿¤é¥Õ¥¡¥¤¥ë̾¤òµ­²±¤·¤Æ¤ª¤¯
-               $this->filename = $tname;
-               $this->status   = TARLIB_STATUS_CREATE;
-               
-               // ¥À¥ß¡¼¥Ç¡¼¥¿
-               $this->dummydata = join('', array_fill(0, TARLIB_BLK_LEN, "\0"));
-               rewind($this->fp);
-
-               return TRUE;
-       }
-
-       ////////////////////////////////////////////////////////////
-       //
-       // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ë
-       // °ú¿ô  : ¤Ê¤·
-       // ÊÖ¤êÃÍ: ¤Ê¤·
-       //
-       ////////////////////////////////////////////////////////////
-       function close()
-       {
-               if ($this->status == TARLIB_STATUS_CREATE)
-               {
-                       // ¥Ð¥¤¥Ê¥ê¡¼¥¼¥í¤ò1024¥Ð¥¤¥È½ÐÎÏ
-                       flock($this->fp, LOCK_EX);
-                       fwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
-                       fwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
-                       flock($this->fp, LOCK_UN);
-
-                       // ¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ë
-                       if ($this->arc_kind == ARCFILE_TAR_GZ) {
-                               gzclose($this->fp);
-                       } else {
-                                fclose($this->fp);
-                       }
-               }
-               else if ($this->status == TARLIB_STATUS_OPEN)
-               {
-                       if ($this->arc_kind == ARCFILE_TAR_GZ) {
-                               gzclose($this->fp);
-                       } else {
-                                fclose($this->fp);
-                       }
-               }
-
-               $this->status = TARLIB_STATUS_INIT;
-       }
-
-       ////////////////////////////////////////////////////////////
-       //
-       // ´Ø¿ô  : »ØÄꤷ¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Ëtar¥Õ¥¡¥¤¥ë¤òŸ³«¤¹¤ë
-       // °ú¿ô  : Å¸³«¤¹¤ë¥Õ¥¡¥¤¥ë¥Ñ¥¿¡¼¥ó(Àµµ¬É½¸½)
-       // ÊÖ¤êÃÍ: Å¸³«¤·¤¿¥Õ¥¡¥¤¥ë̾¤Î°ìÍ÷
-       // Êä­  : ARAI¤µ¤ó¤Îattach¥×¥é¥°¥¤¥ó¥Ñ¥Ã¥Á¤ò»²¹Í¤Ë¤·¤Þ¤·¤¿
-       //
-       ////////////////////////////////////////////////////////////
-       function extract($pattern )
-       {
-               if ($this->status != TARLIB_STATUS_OPEN) return ''; // Not opened
-               
-               $files = array();
-               $longname = '';
-
-               while(1) {
-                       $buff = fread($this->fp, TARLIB_HDR_LEN);
-                       if (strlen($buff) != TARLIB_HDR_LEN) break;
-
-                       // ¥Õ¥¡¥¤¥ë̾
-                       if ($longname != '') {
-                               $name     = $longname;  // LongLinkÂбþ
-                               $longname = '';
-                       } else {
-                               $name = '';
-                               for ($i = 0; $i < TARLIB_HDR_NAME_LEN; $i++ ) {
-                                       if ($buff{$i + TARLIB_HDR_NAME_OFFSET} != "\0") {
-                                               $name .= $buff{$i + TARLIB_HDR_NAME_OFFSET};
-                                       } else {
-                                               break;
-                                       }
-                               }
-                       }
-
-                       $name = trim($name);
-                       if ($name == '') break; // Å¸³«½ªÎ»
-
-                       // ¥Á¥§¥Ã¥¯¥µ¥à¤ò¼èÆÀ¤·¤Ä¤Ä¡¢¥Ö¥é¥ó¥¯¤ËÃÖ´¹¤·¤Æ¤¤¤¯
-                       $checksum = '';
-                       $chkblanks = TARLIB_DATA_CHKBLANKS;
-                       for ($i = 0; $i < TARLIB_HDR_CHKSUM_LEN; $i++ ) {
-                               $checksum .= $buff{$i + TARLIB_HDR_CHKSUM_OFFSET};
-                               $buff{$i + TARLIB_HDR_CHKSUM_OFFSET} = $chkblanks{$i};
-                       }
-                       list($checksum) = sscanf('0' . trim($checksum), '%i');
-
-                       // Compute checksum
-                       $sum = 0;
-                       for($i = 0; $i < TARLIB_BLK_LEN; $i++ ) {
-                               $sum += 0xff & ord($buff{$i});
-                       }
-                       if ($sum != $checksum) break; // Error
-                               
-                       // Size
-                       $size = '';
-                       for ($i = 0; $i < TARLIB_HDR_SIZE_LEN; $i++ ) {
-                               $size .= $buff{$i + TARLIB_HDR_SIZE_OFFSET};
-                       }
-                       list($size) = sscanf('0' . trim($size), '%i');
-
-                       // ceil
-                       // ¥Ç¡¼¥¿¥Ö¥í¥Ã¥¯¤Ï512byte¤Ç¥Ñ¥Ç¥£¥ó¥°¤µ¤ì¤Æ¤¤¤ë
-                       $pdsz = ceil($size / TARLIB_BLK_LEN) * TARLIB_BLK_LEN;
-
-                       // ºÇ½ª¹¹¿·»þ¹ï
-                       $strmtime = '';
-                       for ($i = 0; $i < TARLIB_HDR_MTIME_LEN; $i++ ) {
-                               $strmtime .= $buff{$i + TARLIB_HDR_MTIME_OFFSET};
-                       }
-                       list($mtime) = sscanf('0' . trim($strmtime), '%i');
-
-                       // ¥¿¥¤¥×¥Õ¥é¥° (NOT USED)
-                       // $type = $buff{TARLIB_HDR_TYPE_OFFSET};
-
-                       if ($name == TARLIB_DATA_LONGLINK)
-                       {
-                               // LongLink
-                               $buff = fread( $this->fp, $pdsz );
-                               $longname = substr($buff, 0, $size);
-                       }
-                       else if (preg_match("/$pattern/", $name) )
-//                     if ($type == 0 && preg_match("/$pattern/", $name) )
-                       {
-                               $buff = fread($this->fp, $pdsz);
-
-                               // ´û¤ËƱ¤¸¥Õ¥¡¥¤¥ë¤¬¤¢¤ë¾ì¹ç¤Ï¾å½ñ¤­¤µ¤ì¤ë
-                               $fpw = @fopen($name, 'wb');
-                               if ($fpw !== FALSE) {
-                                       fwrite($fpw, $buff, $size);
-                                       fclose($fpw);
-                                       chmod($name, 0666); // Ç°¤Î¤¿¤á¥Ñ¡¼¥ß¥Ã¥·¥ç¥ó¤òÀßÄꤷ¤Æ¤ª¤¯
-                                       touch($name, $mtime); // ºÇ½ª¹¹¿·»þ¹ï¤Î½¤Àµ
-                                       $files[] = $name;
-                               }
-                       }
-                       else
-                       {
-                               // ¥Õ¥¡¥¤¥ë¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë
-                               @fseek($this->fp, $pdsz, SEEK_CUR);
-                       }
-               }
-               return $files;
-       }
-
-       ////////////////////////////////////////////////////////////
-       //
-       // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤ËÄɲ乤ë
+       // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤òÄɲ乤ë
        // °ú¿ô  : $dir    .. ¥Ç¥£¥ì¥¯¥È¥ê̾
        //         $mask   .. Äɲ乤ë¥Õ¥¡¥¤¥ë(Àµµ¬É½¸½)
        //         $decode .. ¥Ú¡¼¥¸Ì¾¤ÎÊÑ´¹¤ò¤¹¤ë¤«
        // ÊÖ¤êÃÍ: ºîÀ®¤·¤¿¥Õ¥¡¥¤¥ë¿ô
-       //
        ////////////////////////////////////////////////////////////
-       function add($dir, $mask, $decode = FALSE)
+       function add_dir($dir, $mask, $decode = FALSE)
        {
                $retvalue = 0;
                
                if ($this->status != TARLIB_STATUS_CREATE)
-                       return ''; // ¥Õ¥¡¥¤¥ë¤¬ºîÀ®¤µ¤ì¤Æ¤¤¤Ê¤¤
+                       return ''; // File is not created
 
                unset($files);
 
                //  »ØÄꤵ¤ì¤¿¥Ñ¥¹¤Î¥Õ¥¡¥¤¥ë¤Î¥ê¥¹¥È¤ò¼èÆÀ¤¹¤ë
-               $dp = @opendir($dir) or
+               $dp = @opendir($dir);
+               if($dp === FALSE) {
+                       @unlink($this->filename);
                        die_message($dir . ' is not found or not readable.');
+               }
+
                while ($filename = readdir($dp)) {
                        if (preg_match("/$mask/", $filename))
                                $files[] = $dir . $filename;
@@ -564,22 +402,19 @@ class tarlib
                $matches = array();
                foreach($files as $name)
                {
-                       // Tar¤Ë³ÊǼ¤¹¤ë¥Õ¥¡¥¤¥ë̾
-                       if ($decode == TRUE)
-                       {
-                               // ¥Õ¥¡¥¤¥ë̾¤ò¥Ú¡¼¥¸Ì¾¤ËÊÑ´¹¤¹¤ë½èÍý
+                       // Tar¤Ë³ÊǼ¤¹¤ë¥Õ¥¡¥¤¥ë̾¤òdecode
+                       if ($decode === FALSE) {
+                               $filename = $name;
+                       } else {
                                $dirname  = dirname(trim($name)) . '/';
                                $filename = basename(trim($name));
-                               if (preg_match("/^((?:[0-9A-F]{2})+)_((?:[0-9A-F]{2})+)/", $filename, $matches))
-                               {
+                               if (preg_match("/^((?:[0-9A-F]{2})+)_((?:[0-9A-F]{2})+)/", $filename, $matches)) {
                                        // attach¥Õ¥¡¥¤¥ë̾
-                                       $filename = decode($matches[1]).'/'.decode($matches[2]);
-                               }
-                               else
-                               {
+                                       $filename = decode($matches[1]) . '/' . decode($matches[2]);
+                               } else {
                                        $pattern = '^((?:[0-9A-F]{2})+)((\.txt|\.gz)*)$';
                                        if (preg_match("/$pattern/", $filename, $matches)) {
-                                               $filename = decode($matches[1]).$matches[2];
+                                               $filename = decode($matches[1]) . $matches[2];
 
                                                // ´í¤Ê¤¤¥³¡¼¥É¤ÏÃÖ´¹¤·¤Æ¤ª¤¯
                                                $filename = str_replace(':',  '_', $filename);
@@ -587,14 +422,9 @@ class tarlib
                                        }
                                }
                                $filename = $dirname . $filename;
-                               if (function_exists('mb_convert_encoding')) {
-                                       // ¥Õ¥¡¥¤¥ë̾¤Îʸ»ú¥³¡¼¥É¤òÊÑ´¹
+                               // ¥Õ¥¡¥¤¥ë̾¤Îʸ»ú¥³¡¼¥É¤òÊÑ´¹
+                               if (function_exists('mb_convert_encoding'))
                                        $filename = mb_convert_encoding($filename, PLUGIN_DUMP_FILENAME_ENCORDING);
-                               }
-                       }
-                       else
-                       {
-                               $filename = $name;
                        }
 
                        // ºÇ½ª¹¹¿·»þ¹ï
@@ -605,50 +435,49 @@ class tarlib
                                // LongLinkÂбþ
                                $size = strlen($filename);
                                // LonkLink¥Ø¥Ã¥ÀÀ¸À®
-                               $tar_data = $this->make_header(TARLIB_DATA_LONGLINK, $size, $mtime, TARLIB_HDR_LINK);
+                               $tar_data = $this->_make_header(TARLIB_DATA_LONGLINK, $size, $mtime, TARLIB_HDR_LINK);
                                // ¥Õ¥¡¥¤¥ë½ÐÎÏ
-                               $this->write_data(join('', $tar_data), $filename, $size);
+                               $this->_write_data(join('', $tar_data), $filename, $size);
                        }
 
                        // ¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤ò¼èÆÀ
                        $size = filesize($name);
                        if ($size == FALSE) {
+                               @unlink($this->filename);
                                die_message($name . ' is not found or not readable.');
-                               continue;       // ¥Õ¥¡¥¤¥ë¤¬¤Ê¤¤
                        }
 
                        // ¥Ø¥Ã¥ÀÀ¸À®
-                       $tar_data = $this->make_header($filename, $size, $mtime, TARLIB_HDR_FILE);
+                       $tar_data = $this->_make_header($filename, $size, $mtime, TARLIB_HDR_FILE);
 
                        // ¥Õ¥¡¥¤¥ë¥Ç¡¼¥¿¤Î¼èÆÀ
                        $fpr = @fopen($name , 'rb');
+                       flock($fpr, LOCK_SH);
                        $data = fread($fpr, $size);
+                       flock($fpr, LOCK_UN);
                        fclose( $fpr );
 
                        // ¥Õ¥¡¥¤¥ë½ÐÎÏ
-                       $this->write_data(join('', $tar_data), $data, $size);
+                       $this->_write_data(join('', $tar_data), $data, $size);
                        ++$retvalue;
                }
                return $retvalue;
        }
        
        ////////////////////////////////////////////////////////////
-       //
-       // ´Ø¿ô  : tar¤Î¥Ø¥Ã¥À¾ðÊó¤òÀ¸À®¤¹¤ë
+       // ´Ø¿ô  : tar¤Î¥Ø¥Ã¥À¾ðÊó¤òÀ¸À®¤¹¤ë (add)
        // °ú¿ô  : $filename .. ¥Õ¥¡¥¤¥ë̾
        //         $size     .. ¥Ç¡¼¥¿¥µ¥¤¥º
        //         $mtime    .. ºÇ½ª¹¹¿·Æü
        //         $typeflag .. TypeFlag (file/link)
        // Ìá¤êÃÍ: tar¥Ø¥Ã¥À¾ðÊó
-       //
        ////////////////////////////////////////////////////////////
-       function make_header($filename, $size, $mtime, $typeflag)
+       function _make_header($filename, $size, $mtime, $typeflag)
        {
                $tar_data = array_fill(0, TARLIB_HDR_LEN, "\0");
                
                // ¥Õ¥¡¥¤¥ë̾¤òÊݸ
-               for($i = 0; $i < strlen($filename); $i++ )
-               {
+               for($i = 0; $i < strlen($filename); $i++ ) {
                        if ($i < TARLIB_HDR_NAME_LEN) {
                                $tar_data[$i + TARLIB_HDR_NAME_OFFSET] = $filename{$i};
                        } else {
@@ -699,27 +528,190 @@ class tarlib
                for($i = 0; $i < strlen($strchksum); $i++ ) {
                        $tar_data[$i + TARLIB_HDR_CHKSUM_OFFSET] = $strchksum{$i};
                }
+
                return $tar_data;
        }
        
        ////////////////////////////////////////////////////////////
-       //
-       // ´Ø¿ô  : tar¥Ç¡¼¥¿¤Î¥Õ¥¡¥¤¥ë½ÐÎÏ
+       // ´Ø¿ô  : tar¥Ç¡¼¥¿¤Î¥Õ¥¡¥¤¥ë½ÐÎÏ (add)
        // °ú¿ô  : $header .. tar¥Ø¥Ã¥À¾ðÊó
        //         $body   .. tar¥Ç¡¼¥¿
        //         $size   .. ¥Ç¡¼¥¿¥µ¥¤¥º
        // Ìá¤êÃÍ: ¤Ê¤·
-       //
        ////////////////////////////////////////////////////////////
-       function write_data($header, $body, $size)
+       function _write_data($header, $body, $size)
        {
                $fixsize  = ceil($size / TARLIB_BLK_LEN) * TARLIB_BLK_LEN - $size;
 
-               flock($this->fp, LOCK_EX);
-               fwrite($this->fp, $header, TARLIB_HDR_LEN);       // Header
-               fwrite($this->fp, $body, $size);               // Body
-               fwrite($this->fp, $this->dummydata, $fixsize); // Padding
-               flock($this->fp, LOCK_UN);
+               if ($this->arc_kind == TARLIB_KIND_TGZ) {
+                       gzwrite($this->fp, $header, TARLIB_HDR_LEN);    // Header
+                       gzwrite($this->fp, $body, $size);               // Body
+                       gzwrite($this->fp, $this->dummydata, $fixsize); // Padding
+               } else {
+                        fwrite($this->fp, $header, TARLIB_HDR_LEN);    // Header
+                        fwrite($this->fp, $body, $size);               // Body
+                        fwrite($this->fp, $this->dummydata, $fixsize); // Padding
+               }
+       }
+
+       ////////////////////////////////////////////////////////////
+       // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤ò³«¤¯
+       // °ú¿ô  : tar¥Õ¥¡¥¤¥ë̾
+       // ÊÖ¤êÃÍ: TRUE .. À®¸ù , FALSE .. ¼ºÇÔ
+       ////////////////////////////////////////////////////////////
+       function open($name = '', $kind = 'tgz')
+       {
+               if (! PLUGIN_DUMP_ALLOW_RESTORE) return FALSE; // Not allowed
+
+               if ($name != '') $this->filename = $name;
+
+               if ($kind == 'tgz') {
+                       $this->arc_kind = TARLIB_KIND_TGZ;
+                       $this->fp = gzopen($this->filename, 'rb');
+               } else {
+                       $this->arc_kind = TARLIB_KIND_TAR;
+                       $this->fp =  fopen($this->filename, 'rb');
+               }
+
+               if ($this->fp === FALSE) {
+                       return FALSE;   // No such file
+               } else {
+                       $this->status = TARLIB_STATUS_OPEN;
+                       rewind($this->fp);
+                       return TRUE;
+               }
        }
+
+       ////////////////////////////////////////////////////////////
+       // ´Ø¿ô  : »ØÄꤷ¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Ëtar¥Õ¥¡¥¤¥ë¤òŸ³«¤¹¤ë
+       // °ú¿ô  : Å¸³«¤¹¤ë¥Õ¥¡¥¤¥ë¥Ñ¥¿¡¼¥ó(Àµµ¬É½¸½)
+       // ÊÖ¤êÃÍ: Å¸³«¤·¤¿¥Õ¥¡¥¤¥ë̾¤Î°ìÍ÷
+       // Êä­  : ARAI¤µ¤ó¤Îattach¥×¥é¥°¥¤¥ó¥Ñ¥Ã¥Á¤ò»²¹Í¤Ë¤·¤Þ¤·¤¿
+       ////////////////////////////////////////////////////////////
+       function extract($pattern)
+       {
+               if ($this->status != TARLIB_STATUS_OPEN) return ''; // Not opened
+               
+               $files = array();
+               $longname = '';
+
+               while(1) {
+                       $buff = fread($this->fp, TARLIB_HDR_LEN);
+                       if (strlen($buff) != TARLIB_HDR_LEN) break;
+
+                       // ¥Õ¥¡¥¤¥ë̾
+                       $name = '';
+                       if ($longname != '') {
+                               $name     = $longname;  // LongLinkÂбþ
+                               $longname = '';
+                       } else {
+                               for ($i = 0; $i < TARLIB_HDR_NAME_LEN; $i++ ) {
+                                       if ($buff{$i + TARLIB_HDR_NAME_OFFSET} != "\0") {
+                                               $name .= $buff{$i + TARLIB_HDR_NAME_OFFSET};
+                                       } else {
+                                               break;
+                                       }
+                               }
+                       }
+                       $name = trim($name);
+
+                       if ($name == '') break; // Å¸³«½ªÎ»
+
+                       // ¥Á¥§¥Ã¥¯¥µ¥à¤ò¼èÆÀ¤·¤Ä¤Ä¡¢¥Ö¥é¥ó¥¯¤ËÃÖ´¹¤·¤Æ¤¤¤¯
+                       $checksum = '';
+                       $chkblanks = TARLIB_DATA_CHKBLANKS;
+                       for ($i = 0; $i < TARLIB_HDR_CHKSUM_LEN; $i++ ) {
+                               $checksum .= $buff{$i + TARLIB_HDR_CHKSUM_OFFSET};
+                               $buff{$i + TARLIB_HDR_CHKSUM_OFFSET} = $chkblanks{$i};
+                       }
+                       list($checksum) = sscanf('0' . trim($checksum), '%i');
+
+                       // Compute checksum
+                       $sum = 0;
+                       for($i = 0; $i < TARLIB_BLK_LEN; $i++ ) {
+                               $sum += 0xff & ord($buff{$i});
+                       }
+                       if ($sum != $checksum) break; // Error
+                               
+                       // Size
+                       $size = '';
+                       for ($i = 0; $i < TARLIB_HDR_SIZE_LEN; $i++ ) {
+                               $size .= $buff{$i + TARLIB_HDR_SIZE_OFFSET};
+                       }
+                       list($size) = sscanf('0' . trim($size), '%i');
+
+                       // ceil
+                       // ¥Ç¡¼¥¿¥Ö¥í¥Ã¥¯¤Ï512byte¤Ç¥Ñ¥Ç¥£¥ó¥°¤µ¤ì¤Æ¤¤¤ë
+                       $pdsz = ceil($size / TARLIB_BLK_LEN) * TARLIB_BLK_LEN;
+
+                       // ºÇ½ª¹¹¿·»þ¹ï
+                       $strmtime = '';
+                       for ($i = 0; $i < TARLIB_HDR_MTIME_LEN; $i++ ) {
+                               $strmtime .= $buff{$i + TARLIB_HDR_MTIME_OFFSET};
+                       }
+                       list($mtime) = sscanf('0' . trim($strmtime), '%i');
+
+                       // ¥¿¥¤¥×¥Õ¥é¥°
+//                      $type = $buff{TARLIB_HDR_TYPE_OFFSET};
+
+                       if ($name == TARLIB_DATA_LONGLINK) {
+                               // LongLink
+                               $buff     = fread($this->fp, $pdsz);
+                               $longname = substr($buff, 0, $size);
+                       } else if (preg_match("/$pattern/", $name) ) {
+//                     } else if ($type == 0 && preg_match("/$pattern/", $name) ) {
+                               $buff = fread($this->fp, $pdsz);
+
+                               // ´û¤ËƱ¤¸¥Õ¥¡¥¤¥ë¤¬¤¢¤ë¾ì¹ç¤Ï¾å½ñ¤­¤µ¤ì¤ë
+                               $fpw = @fopen($name, 'wb');
+                               if ($fpw !== FALSE) {
+                                       flock($fpw, LOCK_EX);
+                                       fwrite($fpw, $buff, $size);
+                                       @chmod($name, 0666);
+                                       @touch($name, $mtime);
+                                       flock($fpw, LOCK_UN);
+
+                                       fclose($fpw);
+                                       $files[] = $name;
+                               }
+                       } else {
+                               // ¥Õ¥¡¥¤¥ë¥Ý¥¤¥ó¥¿¤ò¿Ê¤á¤ë
+                               @fseek($this->fp, $pdsz, SEEK_CUR);
+                       }
+               }
+               return $files;
+       }
+
+       ////////////////////////////////////////////////////////////
+       // ´Ø¿ô  : tar¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ë
+       // °ú¿ô  : ¤Ê¤·
+       // ÊÖ¤êÃÍ: ¤Ê¤·
+       ////////////////////////////////////////////////////////////
+       function close()
+       {
+               if ($this->status == TARLIB_STATUS_CREATE) {
+                       // ¥Õ¥¡¥¤¥ë¤òÊĤ¸¤ë
+                       if ($this->arc_kind == TARLIB_KIND_TGZ) {
+                               // ¥Ð¥¤¥Ê¥ê¡¼¥¼¥í¤ò1024¥Ð¥¤¥È½ÐÎÏ
+                               gzwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
+                               gzwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
+                               gzclose($this->fp);
+                       } else {
+                               // ¥Ð¥¤¥Ê¥ê¡¼¥¼¥í¤ò1024¥Ð¥¤¥È½ÐÎÏ
+                               fwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
+                               fwrite($this->fp, $this->dummydata, TARLIB_HDR_LEN);
+                               fclose($this->fp);
+                       }
+               } else if ($this->status == TARLIB_STATUS_OPEN) {
+                       if ($this->arc_kind == TARLIB_KIND_TGZ) {
+                               gzclose($this->fp);
+                       } else {
+                                fclose($this->fp);
+                       }
+               }
+
+               $this->status = TARLIB_STATUS_INIT;
+       }
+
 }
 ?>