OSDN Git Service

BugTrack/566 CVS キーワード置換調整, SKIN_DIR='./skin/'
[pukiwiki/pukiwiki.git] / plugin / attach.inc.php
index 6fd54c7..b71ff9f 100644 (file)
-<?
-// ¥×¥é¥°¥¤¥ó attach
+<?php
+/////////////////////////////////////////////////
+// PukiWiki - Yet another WikiWikiWeb clone.
+//
+//  $Id: attach.inc.php,v 1.39 2004/03/18 10:02:13 arino Exp $
+//
 
-// changed by Y.MASUI <masui@hisec.co.jp> http://masui.net/pukiwiki/
-// $Id: attach.inc.php,v 1.9 2002/08/21 17:22:34 masui Exp $
+/*
+ ¥×¥é¥°¥¤¥ó attach
 
-// set PHP value to enable file upload
-ini_set("file_uploads","1");
-
-// upload dir(must set end of /)
-define("UPLOAD_DIR","./attach/");
+ changed by Y.MASUI <masui@hisec.co.jp> http://masui.net/pukiwiki/
+ modified by PANDA <panda@arino.jp> http://home.arino.jp/
+*/
 
 // max file size for upload on PHP(PHP default 2MB)
-ini_set("upload_max_filesize","2M");
+ini_set('upload_max_filesize','2M');
 
 // max file size for upload on script of PukiWiki(default 1MB)
-define("MAX_FILESIZE",1000000);
+define('MAX_FILESIZE',1000000);
+
+// ´ÉÍý¼Ô¤À¤±¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤ò¥¢¥Ã¥×¥í¡¼¥É¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë
+define('ATTACH_UPLOAD_ADMIN_ONLY',FALSE); // FALSE or TRUE
+// ´ÉÍý¼Ô¤À¤±¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤òºï½ü¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë
+define('ATTACH_DELETE_ADMIN_ONLY',FALSE); // FALSE or TRUE
+// ´ÉÍý¼Ô¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤òºï½ü¤¹¤ë¤È¤­¤Ï¡¢¥Ð¥Ã¥¯¥¢¥Ã¥×¤òºî¤é¤Ê¤¤
+// ATTACH_DELETE_ADMIN_ONLY=TRUE¤Î¤È¤­Í­¸ú
+define('ATTACH_DELETE_ADMIN_NOBACKUP',FALSE); // FALSE or TRUE
+
+// ¥¢¥Ã¥×¥í¡¼¥É/ºï½ü»þ¤Ë¥Ñ¥¹¥ï¡¼¥É¤òÍ׵᤹¤ë(ADMIN_ONLY¤¬Í¥Àè)
+define('ATTACH_PASSWORD_REQUIRE',FALSE); // FALSE or TRUE
+
+// ¥Õ¥¡¥¤¥ë¤Î¥¢¥¯¥»¥¹¸¢
+define('ATTACH_FILE_MODE',0644);
+//define('ATTACH_FILE_MODE',0604); // for XREA.COM
 
 // file icon image
-define("FILE_ICON","<img src=\"./image/file.gif\" width=\"20\" height=\"20\" alt=\"file\" style=\"border-width:0px\">");
+if (!defined('FILE_ICON'))
+{
+       define('FILE_ICON','<img src="./image/file.png" width="20" height="20" alt="file" style="border-width:0px" />');
+}
+
+// mime-type¤òµ­½Ò¤·¤¿¥Ú¡¼¥¸
+define('ATTACH_CONFIG_PAGE_MIME','plugin/attach/mime-type');
 
+//-------- convert
 function plugin_attach_convert()
 {
-       global $script,$vars,$max_size,$_attach_plugin_files;
-       global $_msg_attach_filelist,$_msg_maxsize,$_msg_delete,$_btn_upload,$_btn_delete,$_msg_attachfile;
+       global $vars;
        
-       $ret = "";
-       $decoded_pgname = encode($vars["page"]);
-       $count = 0;
+       if (!ini_get('file_uploads'))
+       {
+               return 'file_uploads disabled';
+       }
        
-       $icon = FILE_ICON;
+       $nolist = $noform = FALSE;
        
-       if ($dir = @opendir(UPLOAD_DIR))
+       if (func_num_args() > 0)
        {
-               while($file = readdir($dir))
+               foreach (func_get_args() as $arg)
                {
-                       if($file == ".." || $file == ".") continue;
-                       if(!preg_match("/^${decoded_pgname}_([^.]+)$/",$file,$match)) continue;
-                       
-                       $lastmod = date("Y/m/d H:i:s",filemtime(UPLOAD_DIR.$file));
-                       
-                       settype($dfile_size,"double");
-                       $dfile_size = round(filesize(UPLOAD_DIR.$file)/1000,1);
-                       if($dfile_size == 0) $dfile_size = 0.1;
-                       $file_size = sprintf("%01.1f",$dfile_size)."KB";
-                       
-                       $filename = decode($match[1]);
-                       $filename_url = rawurlencode($filename);
-                       $refername_url = rawurlencode($vars[page]);
-                       
-                       $counter = '';
-                       if(file_exists(UPLOAD_DIR.$file.'.log')) {
-                               $list = file(UPLOAD_DIR.$file.'.log');
-                               
-                               $counter = ' <span class="small">' . sprintf($_attach_plugin_files,chop($list[0])) . '</span>';
-                       }
-                       
-                       $del = "[<a href=\"$script?plugin=attach&amp;mode=confirm&amp;delfile=${filename_url}&amp;refer=${refername_url}\" title=\"".str_replace('$1',$filename,$_msg_delete)."\">$_btn_delete</a>]";
-                       $open = "<a href=\"$script?plugin=attach&amp;openfile=${filename_url}&amp;refer=${refername_url}\" title=\"$lastmod $file_size\">$icon$filename</a>$counter\n";
-                       
-                       $into = "$open <span class=\"small\">$del</span>";
-                       
-                       $attach_files[$lastmod.++$count] = $into;
+                       $arg = strtolower($arg);
+                       $nolist |= ($arg == 'nolist');
+                       $noform |= ($arg == 'noform');
                }
-               closedir($dir);
-               @krsort($attach_files);
        }
+       $ret = '';
+       if (!$nolist)
+       {
+               $obj = &new AttachPages($vars['page']);
+               $ret .= $obj->toString($vars['page'],TRUE);
+       }
+       if (!$noform)
+       {
+               $ret .= attach_form($vars['page']);
+       }
+       
+       return $ret;
+}
+
+//-------- action
+function plugin_attach_action()
+{
+       global $vars;
        
-       $max_size = number_format(MAX_FILESIZE/1000);
-       $max_size.= "KB";
+       // backward compatible
+       if (array_key_exists('openfile',$vars))
+       {
+               $vars['pcmd'] = 'open';
+               $vars['file'] = $vars['openfile'];
+       }
+       if (array_key_exists('delfile',$vars))
+       {
+               $vars['pcmd'] = 'delete';
+               $vars['file'] = $vars['delfile'];
+       }
        
-       $args = func_get_args();
+       $age = array_key_exists('age',$vars) ? $vars['age'] : 0;
+       $pcmd = array_key_exists('pcmd',$vars) ? $vars['pcmd'] : '';
        
-       if(is_array($attach_files))
+       // Authentication
+       if (array_key_exists('refer',$vars) and is_pagename($vars['refer']))
        {
-               if($args[0]===FALSE) $ret.= "$_msg_attachfile: ";
-               $ret.= join("\n&nbsp;&nbsp;",$attach_files)."\n";
+               $read_cmds = array('info','open','list');
+               in_array($pcmd,$read_cmds) ?
+                       check_readable($vars['refer']) : check_editable($vars['refer']);
        }
        
-       if($args[0]!==FALSE)
+       // Upload
+       if (array_key_exists('attach_file',$_FILES))
        {
-               $ret.= "<br />\n";
-               
-               $ret.= "<form enctype=\"multipart/form-data\" action=\"$script\" method=\"post\">\n";
-               $ret.= "<div>\n";
-               $ret.= "<input type=\"hidden\" name=\"plugin\" value=\"attach\" />\n";
-               $ret.= "<input type=\"hidden\" name=\"refer\" value=\"".htmlspecialchars($vars["page"])."\">\n";
-               $ret.= "<input type=\"hidden\" name=\"max_file_size\" value=\"".MAX_FILESIZE."\" />\n";
-               $ret.= "<span class=\"small\">[<a href=\"$script?plugin=attach&amp;pcmd=list\">$_msg_attach_filelist</a>]</span><br />\n";
-               $ret.= "<span class=\"small\">".str_replace('$1',$max_size,$_msg_maxsize)."</span><br />\n";
-               $ret.= "$_msg_attachfile: <input type=\"file\" name=\"attach_file\" />\n";
-               $ret.= "<input type=\"submit\" value=\"$_btn_upload\" /><br />\n";
-               $ret.= "</div>\n";
-               $ret.= "</form>\n";
+               $pass = array_key_exists('pass',$vars) ? md5($vars['pass']) : NULL;
+               return attach_upload($_FILES['attach_file'],$vars['refer'],$pass);
        }
        
-       return $ret;
+       switch ($pcmd)
+       {
+               case 'info':    return attach_info();
+               case 'delete':  return attach_delete();
+               case 'open':    return attach_open();
+               case 'list':    return attach_list();
+               case 'freeze':  return attach_freeze(TRUE);
+               case 'unfreeze':return attach_freeze(FALSE);
+               case 'upload':  return attach_showform();
+       }
+       if ($vars['page'] == '' or !is_page($vars['page']))
+       {
+               return attach_list();
+       }
+       
+       return attach_showform();
 }
-function plugin_attach_action()
+//-------- call from skin
+function attach_filelist()
 {
-       global $vars,$script,$max_size,$HTTP_POST_FILES;
-       global $_title_uploaded,$_title_file_deleted,$_title_notfound,$_msg_noparm,$_msg_already_exists,$_msg_attach_filelist,$_msg_delete,$_msg_exceed,$_btn_delete;
-       global $_msg_maxsize,$_btn_upload,$_msg_attachfile,$_title_upload,$_title_confirm_delete,$_msg_confirm_delete;
+       global $vars,$_attach_messages;
        
-       $postfiles = $HTTP_POST_FILES;
-       $icon = FILE_ICON;
+       $obj = &new AttachPages($vars['page'],0);
 
-       $vars["mode"] = rawurldecode($vars["mode"]);
-       $vars["openfile"] = rawurldecode($vars["openfile"]);
-       $vars["delfile"] = rawurldecode($vars["delfile"]);
-       $vars["refer"] = rawurldecode($vars["refer"]);
+       if (!array_key_exists($vars['page'],$obj->pages))
+       {
+               return '';
+       }
+       return $_attach_messages['msg_file'].': '.$obj->toString($vars['page'],TRUE)."\n";
+}
+//-------- ¼ÂÂÎ
+//¥Õ¥¡¥¤¥ë¥¢¥Ã¥×¥í¡¼¥É
+function attach_upload($file,$page,$pass=NULL)
+{
+// $pass=NULL : ¥Ñ¥¹¥ï¡¼¥É¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤¤
+// $pass=TRUE : ¥¢¥Ã¥×¥í¡¼¥Éµö²Ä
+       global $adminpass,$_attach_messages;
+       
+       if ($file['tmp_name'] == '' or !is_uploaded_file($file['tmp_name']))
+       {
+               return array('result'=>FALSE);
+       }               
+       if ($file['size'] > MAX_FILESIZE)
+       {
+               return array('result'=>FALSE,'msg'=>$_attach_messages['err_exceed']);
+       }
+       if (!is_pagename($page) or ($pass !== TRUE and !is_editable($page)))
+       {
+               return array('result'=>FALSE,'msg'=>$_attach_messages['err_noparm']);
+       }
+       if (ATTACH_UPLOAD_ADMIN_ONLY and $pass !== TRUE
+               and ($pass === NULL or $pass != $adminpass))
+       {
+               return array('result'=>FALSE,'msg'=>$_attach_messages['err_adminpass']);
+       }
+       
+       $obj = &new AttachFile($page,$file['name']);    
+       
+       if ($obj->exist)
+       {
+               return array('result'=>FALSE,'msg'=>$_attach_messages['err_exists']);
+       }
+       if (move_uploaded_file($file['tmp_name'],$obj->filename))
+       {
+               chmod($obj->filename,ATTACH_FILE_MODE);
+       }
+       
+       if (is_page($page))
+       {
+               touch(get_filename($page));
+       }
+       
+       $obj->getstatus();
+       $obj->status['pass'] = ($pass !== TRUE and $pass !== NULL) ? $pass : '';
+       $obj->putstatus();
 
-       if(is_uploaded_file($postfiles["attach_file"]["tmp_name"]))
+       return array('result'=>TRUE,'msg'=>$_attach_messages['msg_uploaded']);
+}
+//¾ÜºÙ¥Õ¥©¡¼¥à¤òɽ¼¨
+function attach_info($err='')
+{
+       global $vars,$_attach_messages;
+       
+       foreach (array('refer','file','age') as $var)
        {
-               if($postfiles["attach_file"]["size"] > MAX_FILESIZE) return array("msg" => $_msg_exceed);
-               if(is_freeze($vars["refer"]) || !is_editable($vars["refer"])) return array("msg" => $_msg_noparm);
-               
-               $filename = encode($vars["refer"])."_".encode($postfiles["attach_file"]["name"]);
-               
-               if(file_exists(UPLOAD_DIR.$filename)) return array("msg" => $_msg_already_exists);
-               
-               move_uploaded_file($postfiles["attach_file"]["tmp_name"],UPLOAD_DIR.$filename);
-               
-               if(file_exists(DATA_DIR.encode($vars["refer"]).".txt"))
-                       @touch(DATA_DIR.encode($vars["refer"]).".txt");
-               
-               return array("msg" => $_title_uploaded);
-       }
-       else if($vars["delfile"])
-       {
-                if($vars["mode"] == "confirm") {
-                 $form = "<form action=\"$script\" method=\"post\">\n";
-                 $form .= "<div>\n";
-                 $form .= "<input type=\"hidden\" name=\"plugin\" value=\"attach\" />\n";
-                 $form .= "<input type=\"hidden\" name=\"refer\" value=\"".htmlspecialchars($vars["refer"])."\" />\n";
-                 $form .= "<input type=\"hidden\" name=\"delfile\" value=\"".htmlspecialchars($vars["delfile"])."\" />\n";
-                 $form .= "<input type=\"submit\" value=\"$_btn_delete\" />\n";
-                 $form .= "</div>\n";
-                 $form .= "</form>";
+               $$var = array_key_exists($var,$vars) ? $vars[$var] : '';
+       }
+       
+       $obj = &new AttachFile($refer,$file,$age);
+       return $obj->getstatus() ? $obj->info($err) : array('msg'=>$_attach_messages['err_notfound']);
+}
+//ºï½ü
+function attach_delete()
+{
+       global $vars,$_attach_messages;
+       
+       foreach (array('refer','file','age','pass') as $var)
+       {
+               $$var = array_key_exists($var,$vars) ? $vars[$var] : '';
+       }
+       
+       if (is_freeze($refer) or !is_editable($refer))
+       {
+               return array('msg'=>$_attach_messages['err_noparm']);
+       }
+       
+       $obj = &new AttachFile($refer,$file,$age);
+       return $obj->getstatus() ? $obj->delete($pass) : array('msg'=>$_attach_messages['err_notfound']);
+}
+//Åà·ë
+function attach_freeze($freeze)
+{
+       global $vars,$_attach_messages;
+       
+       foreach (array('refer','file','age','pass') as $var)
+       {
+               $$var = array_key_exists($var,$vars) ? $vars[$var] : '';
+       }
+       
+       if (is_freeze($refer) or !is_editable($refer))
+       {
+               return array('msg'=>$_attach_messages['err_noparm']);
+       }
+       
+       $obj = &new AttachFile($refer,$file,$age);
+       return $obj->getstatus() ? $obj->freeze($freeze,$pass) : array('msg'=>$_attach_messages['err_notfound']);
+}
+//¥À¥¦¥ó¥í¡¼¥É
+function attach_open()
+{
+       global $vars,$_attach_messages;
+       
+       foreach (array('refer','file','age') as $var)
+       {
+               $$var = array_key_exists($var,$vars) ? $vars[$var] : '';
+       }
+       
+       $obj = &new AttachFile($refer,$file,$age);
+       return $obj->getstatus() ? $obj->open() : array('msg'=>$_attach_messages['err_notfound']);
+}
+//°ìÍ÷¼èÆÀ
+function attach_list()
+{
+       global $vars;
+       global $_attach_messages;
+       
+       $refer = array_key_exists('refer',$vars) ? $vars['refer'] : '';
+       
+       $obj = &new AttachPages($refer);
+       
+       $msg = $_attach_messages[$refer == '' ? 'msg_listall' : 'msg_listpage'];
+       $body = ($refer == '' or array_key_exists($refer,$obj->pages)) ?
+               $obj->toString($refer,FALSE) :
+               $_attach_messages['err_noexist'];
+       return array('msg'=>$msg,'body'=>$body);
+}
+//¥¢¥Ã¥×¥í¡¼¥É¥Õ¥©¡¼¥à¤òɽ¼¨
+function attach_showform()
+{
+       global $vars;
+       global $_attach_messages;
+       
+       $vars['refer'] = $vars['page'];
+       $body = ini_get('file_uploads') ? attach_form($vars['page']) : 'file_uploads disabled.';
+       
+       return array('msg'=>$_attach_messages['msg_upload'],'body'=>$body);
+}
 
-                 $retvars["body"] = sprintf($_msg_confirm_delete,$vars["delfile"],$form);
-                 $retvars["msg"] = sprintf($_title_confirm_delete,$vars["delfile"]);
-                 return $retvars;
+//-------- ¥µ¡¼¥Ó¥¹
+//mime-type¤Î·èÄê
+function attach_mime_content_type($filename)
+{
+       $type = 'application/octet-stream'; //default
+       
+       if (!file_exists($filename))
+       {
+               return $type;
+       }
+       $size = @getimagesize($filename);
+       if (is_array($size))
+       {
+               switch ($size[2])
+               {
+                       case 1:
+                               return 'image/gif';
+                       case 2:
+                               return 'image/jpeg';
+                       case 3:
+                               return 'image/png';
+                       case 4:
+                               return 'application/x-shockwave-flash';
                }
-               else {
-                 $filename = encode($vars["refer"])."_".encode($vars["delfile"]);
-                 if(is_freeze($vars["refer"]) || !is_editable($vars["refer"])) return array("msg" => $_msg_noparm);
-               
-                 if(!file_exists(UPLOAD_DIR.$filename))
-                       return array("msg" => $_title_notfound);
+       }
+       
+       if (!preg_match('/_((?:[0-9A-F]{2})+)(?:\.\d+)?$/',$filename,$matches))
+       {
+               return $type;
+       }
+       $filename = decode($matches[1]);
+       
+       // mime-type°ìÍ÷ɽ¤ò¼èÆÀ
+       $config = new Config(ATTACH_CONFIG_PAGE_MIME);
+       $table = $config->read() ? $config->get('mime-type') : array();
+       unset($config); // ¥á¥â¥êÀáÌó
+       
+       foreach ($table as $row)
+       {
+               $_type = trim($row[0]);
+               $exts = preg_split('/\s+|,/',trim($row[1]),-1,PREG_SPLIT_NO_EMPTY);
                
-                 @unlink(UPLOAD_DIR.$filename);
+               foreach ($exts as $ext)
+               {
+                       if (preg_match("/\.$ext$/i",$filename))
+                       {
+                               return $_type;
+                       }
+               }
+       }
+       
+       return $type;
+}
+//¥¢¥Ã¥×¥í¡¼¥É¥Õ¥©¡¼¥à
+function attach_form($page)
+{
+       global $script,$vars;
+       global $_attach_messages;
+       
+       $r_page = rawurlencode($page);
+       $s_page = htmlspecialchars($page);
+       $navi = <<<EOD
+  <span class="small">
+   [<a href="$script?plugin=attach&amp;pcmd=list&amp;refer=$r_page">{$_attach_messages['msg_list']}</a>]
+   [<a href="$script?plugin=attach&amp;pcmd=list">{$_attach_messages['msg_listall']}</a>]
+  </span><br />
+EOD;
 
-                 if(file_exists(DATA_DIR.encode($vars["refer"]).".txt"))
-                   @touch(DATA_DIR.encode($vars["refer"]).".txt");
+       if (!(bool)ini_get('file_uploads'))
+       {
+               return $navi;
+       }
+       
+       $maxsize = MAX_FILESIZE;
+       $msg_maxsize = sprintf($_attach_messages['msg_maxsize'],number_format($maxsize/1000)."KB");
+
+       $pass = '';
+       if (ATTACH_PASSWORD_REQUIRE or ATTACH_UPLOAD_ADMIN_ONLY)
+       {
+               $title = $_attach_messages[ATTACH_UPLOAD_ADMIN_ONLY ? 'msg_adminpass' : 'msg_password'];
+               $pass = '<br />'.$title.': <input type="password" name="pass" size="8" />';
+       }
+       return <<<EOD
+<form enctype="multipart/form-data" action="$script" method="post">
+ <div>
+  <input type="hidden" name="plugin" value="attach" />
+  <input type="hidden" name="pcmd" value="post" />
+  <input type="hidden" name="refer" value="$s_page" />
+  <input type="hidden" name="max_file_size" value="$maxsize" />
+  $navi
+  <span class="small">
+   $msg_maxsize
+  </span><br />
+  {$_attach_messages['msg_file']}: <input type="file" name="attach_file" />
+  $pass
+  <input type="submit" value="{$_attach_messages['btn_upload']}" />
+ </div>
+</form>
+EOD;
+}
+//-------- ¥¯¥é¥¹
+//¥Õ¥¡¥¤¥ë
+class AttachFile
+{
+       var $page,$file,$age,$basename,$filename,$logname;
+       var $time = 0;
+       var $size = 0;
+       var $time_str = '';
+       var $size_str = '';
+       var $status = array('count'=>array(0),'age'=>'','pass'=>'','freeze'=>FALSE);
+       
+       function AttachFile($page,$file,$age=0)
+       {
+               $this->page = $page;
+               $this->file = basename($file);
+               $this->age = is_numeric($age) ? $age : 0;
                
-                 return array("msg" => $_title_file_deleted);
-               }
+               $this->basename = UPLOAD_DIR.encode($page).'_'.encode($this->file);
+               $this->filename = $this->basename . ($age ? '.'.$age : '');
+               $this->logname = $this->basename.'.log';
+               $this->exist = file_exists($this->filename);
+               $this->time = $this->exist ? filemtime($this->filename) - LOCALZONE : 0;
+               $this->md5hash = $this->exist ? md5_file($this->filename) : '';
        }
-       else if($vars["openfile"])
+       // ¥Õ¥¡¥¤¥ë¾ðÊó¼èÆÀ
+       function getstatus()
        {
-               $filename = encode($vars["refer"])."_".encode($vars["openfile"]);
+               if (!$this->exist)
+               {
+                       return FALSE;
+               }
+               // ¥í¥°¥Õ¥¡¥¤¥ë¼èÆÀ
+               if (file_exists($this->logname))
+               {
+                       $data = file($this->logname);
+                       foreach ($this->status as $key=>$value)
+                       {
+                               $this->status[$key] = chop(array_shift($data));
+                       }
+                       $this->status['count'] = explode(',',$this->status['count']);
+               }
+               $this->time_str = get_date('Y/m/d H:i:s',$this->time);
+               $this->size = filesize($this->filename);
+               $this->size_str = sprintf('%01.1f',round($this->size)/1000,1).'KB';
+               $this->type = attach_mime_content_type($this->filename);
                
-               if(!file_exists(UPLOAD_DIR.$filename))
-                       return array("msg" => $_title_notfound);
+               return TRUE;
+       }
+       //¥¹¥Æ¡¼¥¿¥¹Êݸ
+       function putstatus()
+       {
+               $this->status['count'] = join(',',$this->status['count']);
+               $fp = fopen($this->logname,'wb')
+                       or die_message('cannot write '.$this->logname);
+               set_file_buffer($fp, 0);
+               flock($fp,LOCK_EX);
+               rewind($fp);
+               foreach ($this->status as $key=>$value)
+               {
+                       fwrite($fp,$value."\n");
+               }
+               flock($fp,LOCK_UN);
+               fclose($fp);
+       }
+       // ÆüÉÕ¤ÎÈæ³Ó´Ø¿ô
+       function datecomp($a,$b)
+       {
+               return ($a->time == $b->time) ? 0 : (($a->time > $b->time) ? -1 : 1);
+       }
+       function toString($showicon,$showinfo)
+       {
+               global $script,$date_format,$time_format,$weeklabels;
+               global $_attach_messages;
                
-               download_file(UPLOAD_DIR.$filename,$vars["openfile"]);
-
-               die();
+               $this->getstatus();
+               $param  = '&amp;file='.rawurlencode($this->file).'&amp;refer='.rawurlencode($this->page).
+                       ($this->age ? '&amp;age='.$this->age : '');
+               $title = $this->time_str.' '.$this->size_str;
+               $label = ($showicon ? FILE_ICON : '').htmlspecialchars($this->file);
+               if ($this->age)
+               {
+                       $label .= ' (backup No.'.$this->age.')';
+               }
+               $info = $count = '';
+               if ($showinfo)
+               {
+                       $_title = str_replace('$1',rawurlencode($this->file),$_attach_messages['msg_info']);
+                       $info = "\n<span class=\"small\">[<a href=\"$script?plugin=attach&amp;pcmd=info$param\" title=\"$_title\">{$_attach_messages['btn_info']}</a>]</span>";
+                       $count = ($showicon and !empty($this->status['count'][$this->age])) ?
+                               sprintf($_attach_messages['msg_count'],$this->status['count'][$this->age]) : '';
+               }
+               return "<a href=\"$script?plugin=attach&amp;pcmd=open$param\" title=\"$title\">$label</a>$count$info";
        }
-       else if($vars["pcmd"] == "list")
+       // ¾ðÊóɽ¼¨
+       function info($err)
        {
-               if ($dir = @opendir(UPLOAD_DIR))
+               global $script,$_attach_messages;
+               
+               $r_page = rawurlencode($this->page);
+               $s_page = htmlspecialchars($this->page);
+               $s_file = htmlspecialchars($this->file);
+               $s_err = ($err == '') ? '' : '<p style="font-weight:bold">'.$_attach_messages[$err].'</p>';
+               
+               if ($this->age)
+               {
+                       $msg_freezed = '';
+                       $msg_delete  = '<input type="radio" name="pcmd" value="delete" />'.$_attach_messages['msg_delete'];
+                       $msg_delete .= $_attach_messages['msg_require'];
+                       $msg_delete .= '<br />';
+                       $msg_freeze  = '';
+               }
+               else
                {
-                       $pgname_keep = "";
-                       $retbody = "";
-                       $aryret = array();
-                       $pagenames = array();
-                       while($file = readdir($dir))
+                       if ($this->status['freeze'])
                        {
-                               if($file == ".." || $file == "." || strstr($file,".log")!=FALSE) continue;
-                               
-                               settype($dfile_size,"double");
-                               $dfile_size = round(filesize(UPLOAD_DIR.$file)/1000,1);
-                               if($dfile_size == 0) $dfile_size = 0.1;
-                               $file_size = sprintf("%01.1f",$dfile_size)."KB";
-                               
-                               preg_match("/^([^_]+)_([^_]+)$/",$file,$match);
-                               
-                               $pagename = decode($match[1]);
-                               $pagename_url = rawurlencode($pagename);
-                               $filename = decode($match[2]);
-                               $filename_url = rawurlencode($filename);
-                               $passage = get_pg_passage($pagename);
-                               
-                               $pagename = strip_bracket($pagename);
-                               $pagenames[$pagename] = "<li><a href=\"$script?${pagename_url}\">$pagename</a>$passage</li>\n";
-                               
-                               $lastmod = date("Y/m/d H:i:s",filemtime(UPLOAD_DIR.$file));
-                               
-                               $del = "[<a href=\"$script?plugin=attach&amp;mode=confirm&amp;delfile=${filename_url}&amp;refer=${pagename_url}\" title=\"".str_replace('$1',$filename,$_msg_delete)."\">$_btn_delete</a>]";
-                               
-                               $open = "<a href=\"$script?plugin=attach&amp;openfile=${filename_url}&amp;refer=${pagename_url}\" title=\"$lastmod $file_size\">$filename</a>";
-
-                               $aryret[$pagename] .= "<li>$open <span class=\"small\">$del</span></li>\n";
+                               $msg_freezed = "<dd>{$_attach_messages['msg_isfreeze']}</dd>";
+                               $msg_delete = '';
+                               $msg_freeze  = '<input type="radio" name="pcmd" value="unfreeze" />'.$_attach_messages['msg_unfreeze'];
+                               $msg_freeze .= $_attach_messages['msg_require'].'<br />';
                        }
-                       closedir($dir);
-                       ksort($aryret);
-                       $retbody = '';
-                       foreach($aryret as $pagename => $list) {
-                               $retbody .= $pagenames[$pagename] . "<ul>\n" . $list . "</ul>\n";
+                       else
+                       {
+                               $msg_freezed = '';
+                               $msg_delete = '<input type="radio" name="pcmd" value="delete" />'.$_attach_messages['msg_delete'];
+                               if (ATTACH_DELETE_ADMIN_ONLY or $this->age)
+                               {
+                                       $msg_delete .= $_attach_messages['msg_require'];
+                               }
+                               $msg_delete .= '<br />';
+                               $msg_freeze  = '<input type="radio" name="pcmd" value="freeze" />'.$_attach_messages['msg_freeze'];
+                               $msg_freeze .= "{$_attach_messages['msg_require']}<br />";
                        }
                }
+               $info = $this->toString(TRUE,FALSE);
                
-               $retvars["msg"] = $_msg_attach_filelist;
-               $retvars["body"] = "<ul>\n".$retbody."</ul>\n";
-               if($retbody) $retvars["body"] .= "</ul>\n";
+               $retval = array('msg'=>sprintf($_attach_messages['msg_info'],htmlspecialchars($this->file)));
+               $retval['body'] = <<< EOD
+<p class="small">
+ [<a href="$script?plugin=attach&amp;pcmd=list&amp;refer=$r_page">{$_attach_messages['msg_list']}</a>]
+ [<a href="$script?plugin=attach&amp;pcmd=list">{$_attach_messages['msg_listall']}</a>]
+</p>
+<dl>
+ <dt>$info</dt>
+ <dd>{$_attach_messages['msg_page']}:$s_page</dd>
+ <dd>{$_attach_messages['msg_filename']}:{$this->filename}</dd>
+ <dd>{$_attach_messages['msg_md5hash']}:{$this->md5hash}</dd>
+ <dd>{$_attach_messages['msg_filesize']}:{$this->size_str} ({$this->size} bytes)</dd>
+ <dd>Content-type:{$this->type}</dd>
+ <dd>{$_attach_messages['msg_date']}:{$this->time_str}</dd>
+ <dd>{$_attach_messages['msg_dlcount']}:{$this->status['count'][$this->age]}</dd>
+ $msg_freezed
+</dl>
+<hr />
+$s_err
+<form action="$script" method="post">
+ <div>
+  <input type="hidden" name="plugin" value="attach" />
+  <input type="hidden" name="refer" value="$s_page" />
+  <input type="hidden" name="file" value="$s_file" />
+  <input type="hidden" name="age" value="{$this->age}" />
+  $msg_delete
+  $msg_freeze
+  {$_attach_messages['msg_password']}: <input type="password" name="pass" size="8" />
+  <input type="submit" value="{$_attach_messages['btn_submit']}" />
+ </div>
+</form>
+EOD;
+               return $retval;
+       }
+       function delete($pass)
+       {
+               global $adminpass,$_attach_messages;
+                               
+               if ($this->status['freeze'])
+               {
+                       return attach_info('msg_isfreeze');
+               }
                
-               return $retvars;
+               if (md5($pass) != $adminpass)
+               {
+                       if (ATTACH_DELETE_ADMIN_ONLY or $this->age)
+                       {
+                               return attach_info('err_adminpass');
+                       }
+                       else if (ATTACH_PASSWORD_REQUIRE and md5($pass) != $this->status['pass'])
+                       {
+                               return attach_info('err_password');
+                       }
+               }
+               //¥Ð¥Ã¥¯¥¢¥Ã¥×
+               if ($this->age or
+                       (ATTACH_DELETE_ADMIN_ONLY and ATTACH_DELETE_ADMIN_NOBACKUP))
+               {
+                       @unlink($this->filename);
+               }
+               else
+               {
+                       do
+                       {
+                               $age = ++$this->status['age'];
+                       }
+                       while (file_exists($this->basename.'.'.$age));
+                       
+                       if (!rename($this->basename,$this->basename.'.'.$age))
+                       {
+                               // ºï½ü¼ºÇÔ why?
+                               return array('msg'=>$_attach_messages['err_delete']);
+                       }
+                       
+                       $this->status['count'][$age] = $this->status['count'][0];
+                       $this->status['count'][0] = 0;
+                       $this->putstatus();
+               }
+               if (is_page($this->page))
+               {
+                       touch(get_filename($this->page));
+               }
+               
+               return array('msg'=>$_attach_messages['msg_deleted']);
        }
-       else if($vars["pcmd"] == "upload" && $vars["page"])
+       function freeze($freeze,$pass)
        {
-               $vars["refer"] = $vars["page"];
+               global $adminpass;
+               
+               if (md5($pass) != $adminpass)
+               {
+                       return attach_info('err_adminpass');
+               }
+               
+               $this->getstatus();
+               $this->status['freeze'] = $freeze;
+               $this->putstatus();
                
-               $max_size = number_format(MAX_FILESIZE/1000);
-               $max_size.= "KB";
+               return array('msg'=>$_attach_messages[$freeze ? 'msg_freezed' : 'msg_unfreezed']);
+       }
+       function open()
+       {
+               $this->getstatus();
+               $this->status['count'][$this->age]++;
+               $this->putstatus();
                
-               $ret.= "<form enctype=\"multipart/form-data\" action=\"$script\" method=\"post\">\n";
-               $ret.= "<blockquote>\n";
-               $ret.= "<input type=\"hidden\" name=\"plugin\" value=\"attach\" />\n";
-               $ret.= "<input type=\"hidden\" name=\"refer\" value=\"".htmlspecialchars($vars["page"])."\" />\n";
-               $ret.= "<input type=\"hidden\" name=\"max_file_size\" value=\"".MAX_FILESIZE."\" />\n";
-               $ret.= "<span class=\"small\">[<a href=\"$script?plugin=attach&amp;pcmd=list\">$_msg_attach_filelist</a>]</span><br />\n";
-               $ret.= "<span class=\"small\">".str_replace('$1',$max_size,$_msg_maxsize)."</span><br />\n";
-               $ret.= "$_msg_attachfile: <input type=\"file\" name=\"attach_file\" />\n";
-               $ret.= "<input type=\"submit\" value=\"$_btn_upload\" /><br />\n";
-               $ret.= "</blockquote>\n";
-               $ret.= "</form>\n";
+               // for japanese (???)
+               $filename = htmlspecialchars(mb_convert_encoding($this->file,'SJIS','auto'));
                
-               $retvars["msg"] = $_title_upload;
-               $retvars["body"] = $ret;
+               ini_set('default_charset','');
+               mb_http_output('pass');
                
-               return $retvars;
+               header('Content-Disposition: inline; filename="'.$filename.'"');
+               header('Content-Length: '.$this->size);
+               header('Content-Type: '.$this->type);
+               @readfile($this->filename);
+               exit;
        }
 }
 
-function attach_filelist()
-{
-       return plugin_attach_convert(FALSE);
-}
-
-function download_file($path_file,$filename)
+// ¥Õ¥¡¥¤¥ë¥³¥ó¥Æ¥Ê
+class AttachFiles
 {
-       $content_length = filesize($path_file);
+       var $page;
+       var $files = array();
        
-       $list = array(1);
-       if(file_exists($path_file.'.log')) {
-               $list = file($path_file.'.log');
-               $list[0] = chop($list[0]) + 1;
+       function AttachFiles($page)
+       {
+               $this->page = $page;
        }
-       $fp = fopen($path_file.'.log','w');
-       foreach ($list as $l) {
-               fputs($fp,$l);
+       function add($file,$age)
+       {
+               $this->files[$file][$age] = &new AttachFile($this->page,$file,$age);
+       }
+       // ¥Õ¥¡¥¤¥ë°ìÍ÷¤ò¼èÆÀ
+       function toString($flat)
+       {
+               global $_title_cannotread;
+               
+               if (!check_readable($this->page,FALSE,FALSE))
+               {
+                       return str_replace('$1',make_pagelink($this->page),$_title_cannotread);
+               }
+               if ($flat)
+               {
+                       return $this->to_flat();
+               }       
+               $ret = '';
+               $files = array_keys($this->files);
+               sort($files);
+               foreach ($files as $file)
+               {
+                       $_files = array();
+                       foreach (array_keys($this->files[$file]) as $age)
+                       {
+                               $_files[$age] = $this->files[$file][$age]->toString(FALSE,TRUE);
+                       }
+                       if (!array_key_exists(0,$_files))
+                       {
+                               $_files[0] = htmlspecialchars($file);
+                       }
+                       ksort($_files);
+                       $_file = $_files[0];
+                       unset($_files[0]);
+                       $ret .= " <li>$_file\n";
+                       if (count($_files))
+                       {
+                               $ret .= "<ul>\n<li>".join("</li>\n<li>",$_files)."</li>\n</ul>\n";
+                       }
+                       $ret .= " </li>\n";
+               }
+               return make_pagelink($this->page)."\n<ul>\n$ret</ul>\n";
+       }
+       // ¥Õ¥¡¥¤¥ë°ìÍ÷¤ò¼èÆÀ(inline)
+       function to_flat()
+       {
+               $ret = '';
+               $files = array();
+               foreach (array_keys($this->files) as $file)
+               {
+                       if (array_key_exists(0,$this->files[$file]))
+                       {
+                               $files[$file] = &$this->files[$file][0];
+                       }
+               }
+               uasort($files,array('AttachFile','datecomp'));
+               foreach (array_keys($files) as $file)
+               {
+                       $ret .= $files[$file]->toString(TRUE,TRUE).' ';
+               }
+               
+               return $ret;
        }
-       fclose($fp);
-       
-       // for japanese
-       if(function_exists("mb_convert_encoding"))
-               $filename = mb_convert_encoding($filename,"SJIS","auto");
-
-       header("Content-Disposition: inline; filename=\"$filename\"");
-       header("Content-Length: ".$content_length);
-       header("Content-Type: application/octet-stream");
-
-       @readfile($path_file);
 }
+// ¥Ú¡¼¥¸¥³¥ó¥Æ¥Ê
+class AttachPages
+{
+       var $pages = array();
+       
+       function AttachPages($page='',$age=NULL)
+       {
 
+               $dir = opendir(UPLOAD_DIR)
+                       or die('directory '.UPLOAD_DIR.' is not exist or not readable.');
+               
+               $page_pattern = ($page == '') ? '(?:[0-9A-F]{2})+' : preg_quote(encode($page),'/');
+               $age_pattern = ($age === NULL) ?
+                       '(?:\.([0-9]+))?' : ($age ?  "\.($age)" : '');
+               $pattern = "/^({$page_pattern})_((?:[0-9A-F]{2})+){$age_pattern}$/";
+               
+               while ($file = readdir($dir))
+               {
+                       if (!preg_match($pattern,$file,$matches))
+                       {
+                               continue;
+                       }
+                       $_page = decode($matches[1]);
+                       $_file = decode($matches[2]);
+                       $_age = array_key_exists(3,$matches) ? $matches[3] : 0;
+                       if (!array_key_exists($_page,$this->pages))
+                       {
+                               $this->pages[$_page] = &new AttachFiles($_page);
+                       }
+                       $this->pages[$_page]->add($_file,$_age);
+               }
+               closedir($dir);
+       }
+       function toString($page='',$flat=FALSE)
+       {
+               if ($page != '')
+               {
+                       if (!array_key_exists($page,$this->pages))
+                       {
+                               return '';
+                       }
+                       return $this->pages[$page]->toString($flat);
+               }
+               $ret = '';
+               $pages = array_keys($this->pages);
+               sort($pages);
+               foreach ($pages as $page)
+               {
+                       $ret .= '<li>'.$this->pages[$page]->toString($flat)."</li>\n";
+               }
+               return "\n<ul>\n".$ret."</ul>\n";
+               
+       }
+}              
 ?>