OSDN Git Service

Set dev site name - PukiWiki Developers' site
[pukiwiki/pukiwiki.git] / plugin / attach.inc.php
index 4dbcdab..01c79cb 100644 (file)
@@ -1,8 +1,8 @@
 <?php
 // PukiWiki - Yet another WikiWikiWeb clone
-// $Id: attach.inc.php,v 1.75 2005/05/22 04:19:06 henoheno Exp $
-// Copyright (C)
-//   2003-2005 PukiWiki Developers Team
+// attach.inc.php
+// Copyright
+//   2003-2016 PukiWiki Development Team
 //   2002-2003 PANDA <panda@arino.jp> http://home.arino.jp/
 //   2002      Y.MASUI <masui@hisec.co.jp> http://masui.net/pukiwiki/
 //   2001-2002 Originally written by yu-ji
 //
 // File attach plugin
 
+// NOTE (PHP > 4.2.3):
+//    This feature is disabled at newer version of PHP.
+//    Set this at php.ini if you want.
 // Max file size for upload on PHP (PHP default: 2MB)
 ini_set('upload_max_filesize', '2M');
 
 // Max file size for upload on script of PukiWikiX_FILESIZE
 define('PLUGIN_ATTACH_MAX_FILESIZE', (1024 * 1024)); // default: 1MB
 
-// ´ÉÍý¼Ô¤À¤±¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤ò¥¢¥Ã¥×¥í¡¼¥É¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë
+// 管理者だけが添付ファイルをアップロードできるようにする
 define('PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY', TRUE); // FALSE or TRUE
 
-// ´ÉÍý¼Ô¤À¤±¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤òºï½ü¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë
+// 管理者だけが添付ファイルを削除できるようにする
 define('PLUGIN_ATTACH_DELETE_ADMIN_ONLY', TRUE); // FALSE or TRUE
 
-// ´ÉÍý¼Ô¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤òºï½ü¤¹¤ë¤È¤­¤Ï¡¢¥Ð¥Ã¥¯¥¢¥Ã¥×¤òºî¤é¤Ê¤¤
-// PLUGIN_ATTACH_DELETE_ADMIN_ONLY=TRUE¤Î¤È¤­Í­¸ú
-define('PLUGIN_ATTACH_DELETE_ADMIN_NOBACKUP', TRUE); // FALSE or TRUE
+// 管理者が添付ファイルを削除するときは、バックアップを作らない
+// PLUGIN_ATTACH_DELETE_ADMIN_ONLY=TRUEのとき有効
+define('PLUGIN_ATTACH_DELETE_ADMIN_NOBACKUP', FALSE); // FALSE or TRUE
 
-// ¥¢¥Ã¥×¥í¡¼¥É/ºï½ü»þ¤Ë¥Ñ¥¹¥ï¡¼¥É¤òÍ׵᤹¤ë(ADMIN_ONLY¤¬Í¥Àè)
+// アップロード/削除時にパスワードを要求する(ADMIN_ONLYが優先)
 define('PLUGIN_ATTACH_PASSWORD_REQUIRE', FALSE); // FALSE or TRUE
 
-// ¥Õ¥¡¥¤¥ë¤Î¥¢¥¯¥»¥¹¸¢
+// 添付ファイル名を変更できるようにする
+define('PLUGIN_ATTACH_RENAME_ENABLE', TRUE); // FALSE or TRUE
+
+// ファイルのアクセス権
 define('PLUGIN_ATTACH_FILE_MODE', 0644);
 //define('PLUGIN_ATTACH_FILE_MODE', 0604); // for XREA.COM
 
@@ -38,7 +44,7 @@ define('PLUGIN_ATTACH_FILE_ICON', '<img src="' . IMAGE_DIR .  'file.png"' .
        ' width="20" height="20" alt="file"' .
        ' style="border-width:0px" />');
 
-// mime-type¤òµ­½Ò¤·¤¿¥Ú¡¼¥¸
+// mime-typeã\82\92è¨\98è¿°ã\81\97ã\81\9fã\83\9aã\83¼ã\82¸
 define('PLUGIN_ATTACH_CONFIG_PAGE_MIME', 'plugin/attach/mime-type');
 
 //-------- convert
@@ -59,7 +65,7 @@ function plugin_attach_convert()
 
        $ret = '';
        if (! $nolist) {
-               $obj  = new AttachPages($page);
+               $obj  = new AttachPages($page);
                $ret .= $obj->toString($page, TRUE);
        }
        if (! $noform) {
@@ -101,26 +107,28 @@ function plugin_attach_action()
        if (isset($_FILES['attach_file'])) {
                // Upload
                return attach_upload($_FILES['attach_file'], $refer, $pass);
-       }
-       switch ($pcmd) {
-       case 'delete':  /*FALLTHROUGH*/
-       case 'freeze':
-       case 'unfreeze':
-               if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
-       }
-       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 ($page == '' || ! is_page($page)) {
-               return attach_list();
        } else {
-               return attach_showform();
+               switch ($pcmd) {
+               case 'delete':  /*FALLTHROUGH*/
+               case 'freeze':
+               case 'unfreeze':
+                       if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
+               }
+               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 'rename'   : return attach_rename();
+               case 'upload'   : return attach_showform();
+               }
+               if ($page == '' || ! is_page($page)) {
+                       return attach_list();
+               } else {
+                       return attach_showform();
+               }
        }
 }
 
@@ -131,7 +139,7 @@ function attach_filelist()
 
        $page = isset($vars['page']) ? $vars['page'] : '';
 
-       $obj = new AttachPages($page, 0);
+       $obj = new AttachPages($page, 0);
 
        if (! isset($obj->pages[$page])) {
                return '';
@@ -141,13 +149,13 @@ function attach_filelist()
        }
 }
 
-//-------- ¼ÂÂÎ
-// ¥Õ¥¡¥¤¥ë¥¢¥Ã¥×¥í¡¼¥É
-// $pass = NULL : ¥Ñ¥¹¥ï¡¼¥É¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤¤
-// $pass = TRUE : ¥¢¥Ã¥×¥í¡¼¥Éµö²Ä
+//-------- 実体
+// ファイルアップロード
+// $pass = NULL : パスワードが指定されていない
+// $pass = TRUE : アップロード許可
 function attach_upload($file, $page, $pass = NULL)
 {
-       global $_attach_messages;
+       global $_attach_messages, $notify, $notify_subject;
 
        if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
 
@@ -178,7 +186,7 @@ function attach_upload($file, $page, $pass = NULL)
                        'msg'=>$_attach_messages['err_adminpass']);
        }
 
-       $obj = new AttachFile($page, $file['name']);
+       $obj = new AttachFile($page, $file['name']);
        if ($obj->exist)
                return array('result'=>FALSE,
                        'msg'=>$_attach_messages['err_exists']);
@@ -187,18 +195,40 @@ function attach_upload($file, $page, $pass = NULL)
                chmod($obj->filename, PLUGIN_ATTACH_FILE_MODE);
 
        if (is_page($page))
-               touch(get_filename($page));
+               pkwk_touch_file(get_filename($page));
 
        $obj->getstatus();
        $obj->status['pass'] = ($pass !== TRUE && $pass !== NULL) ? md5($pass) : '';
        $obj->putstatus();
 
+       if ($notify) {
+               $footer['ACTION']   = 'File attached';
+               $footer['FILENAME'] = & $file['name'];
+               $footer['FILESIZE'] = & $file['size'];
+               $footer['PAGE']     = & $page;
+
+               $footer['URI']      = get_script_uri() .
+                       //'?' . pagename_urlencode($page);
+
+                       // MD5 may heavy
+                       '?plugin=attach' .
+                               '&refer=' . rawurlencode($page) .
+                               '&file='  . rawurlencode($file['name']) .
+                               '&pcmd=info';
+
+               $footer['USER_AGENT']  = TRUE;
+               $footer['REMOTE_ADDR'] = TRUE;
+
+               pkwk_mail_notify($notify_subject, "\n", $footer) or
+                       die('pkwk_mail_notify(): Failed');
+       }
+
        return array(
                'result'=>TRUE,
                'msg'=>$_attach_messages['msg_uploaded']);
 }
 
-// ¾ÜºÙ¥Õ¥©¡¼¥à¤òɽ¼¨
+// 詳細フォームを表示
 function attach_info($err = '')
 {
        global $vars, $_attach_messages;
@@ -206,13 +236,13 @@ function attach_info($err = '')
        foreach (array('refer', 'file', 'age') as $var)
                ${$var} = isset($vars[$var]) ? $vars[$var] : '';
 
-       $obj = new AttachFile($refer, $file, $age);
+       $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;
@@ -220,17 +250,17 @@ function attach_delete()
        foreach (array('refer', 'file', 'age', 'pass') as $var)
                ${$var} = isset($vars[$var]) ? $vars[$var] : '';
 
-       if (is_freeze($refer) || ! is_editable($refer)) {
+       if (is_freeze($refer) || ! is_editable($refer))
                return array('msg'=>$_attach_messages['err_noparm']);
-       } else {
-               $obj = & new AttachFile($refer, $file, $age);
-               return $obj->getstatus() ?
-                       $obj->delete($pass) :
-                       array('msg'=>$_attach_messages['err_notfound']);
-       }
+
+       $obj = new AttachFile($refer, $file, $age);
+       if (! $obj->getstatus())
+               return array('msg'=>$_attach_messages['err_notfound']);
+               
+       return $obj->delete($pass);
 }
 
-// Åà·ë
+// 凍結
 function attach_freeze($freeze)
 {
        global $vars, $_attach_messages;
@@ -242,14 +272,34 @@ function attach_freeze($freeze)
        if (is_freeze($refer) || ! is_editable($refer)) {
                return array('msg'=>$_attach_messages['err_noparm']);
        } else {
-               $obj = new AttachFile($refer, $file, $age);
+               $obj = new AttachFile($refer, $file, $age);
                return $obj->getstatus() ?
                        $obj->freeze($freeze, $pass) :
                        array('msg'=>$_attach_messages['err_notfound']);
        }
 }
 
-// ¥À¥¦¥ó¥í¡¼¥É
+// リネーム
+function attach_rename()
+{
+       global $vars, $_attach_messages;
+
+       foreach (array('refer', 'file', 'age', 'pass', 'newname') as $var) {
+               ${$var} = isset($vars[$var]) ? $vars[$var] : '';
+       }
+
+       if (is_freeze($refer) || ! is_editable($refer)) {
+               return array('msg'=>$_attach_messages['err_noparm']);
+       }
+       $obj = new AttachFile($refer, $file, $age);
+       if (! $obj->getstatus())
+               return array('msg'=>$_attach_messages['err_notfound']);
+
+       return $obj->rename($pass, $newname);
+
+}
+
+// ダウンロード
 function attach_open()
 {
        global $vars, $_attach_messages;
@@ -258,20 +308,20 @@ function attach_open()
                ${$var} = isset($vars[$var]) ? $vars[$var] : '';
        }
 
-       $obj = new AttachFile($refer, $file, $age);
+       $obj = new AttachFile($refer, $file, $age);
        return $obj->getstatus() ?
                $obj->open() :
                array('msg'=>$_attach_messages['err_notfound']);
 }
 
-// °ìÍ÷¼èÆÀ
+// 一覧取得
 function attach_list()
 {
        global $vars, $_attach_messages;
 
        $refer = isset($vars['refer']) ? $vars['refer'] : '';
 
-       $obj = new AttachPages($refer);
+       $obj = new AttachPages($refer);
 
        $msg = $_attach_messages[($refer == '') ? 'msg_listall' : 'msg_listpage'];
        $body = ($refer == '' || isset($obj->pages[$refer])) ?
@@ -281,7 +331,7 @@ function attach_list()
        return array('msg'=>$msg, 'body'=>$body);
 }
 
-// ¥¢¥Ã¥×¥í¡¼¥É¥Õ¥©¡¼¥à¤òɽ¼¨ (action»þ)
+// アップロードフォームを表示 (action時)
 function attach_showform()
 {
        global $vars, $_attach_messages;
@@ -293,53 +343,47 @@ function attach_showform()
        return array('msg'=>$_attach_messages['msg_upload'], 'body'=>$body);
 }
 
-//-------- ¥µ¡¼¥Ó¥¹
-// mime-type¤Î·èÄê
-function attach_mime_content_type($filename)
+//-------- ã\82µã\83¼ã\83\93ã\82¹
+// mime-typeの決定
+function attach_mime_content_type($filename, $displayname)
 {
        $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';
+       $pathinfo = pathinfo($displayname);
+       $ext0 = $pathinfo['extension'];
+       if (preg_match('/^(gif|jpg|jpeg|png|swf)$/i', $ext0)) {
+               $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';
+                       }
                }
        }
-
-       $matches = array();
-       if (! preg_match('/_((?:[0-9A-F]{2})+)(?:\.\d+)?$/', $filename, $matches))
-               return $type;
-
-       $filename = decode($matches[1]);
-
-       // mime-type°ìÍ÷ɽ¤ò¼èÆÀ
+       // mime-type一覧表を取得
        $config = new Config(PLUGIN_ATTACH_CONFIG_PAGE_MIME);
        $table = $config->read() ? $config->get('mime-type') : array();
-       unset($config); // ¥á¥â¥êÀáÌó
-
+       unset($config); // メモリ節約
        foreach ($table as $row) {
                $_type = trim($row[0]);
                $exts = preg_split('/\s+|,/', trim($row[1]), -1, PREG_SPLIT_NO_EMPTY);
                foreach ($exts as $ext) {
-                       if (preg_match("/\.$ext$/i", $filename)) return $_type;
+                       if (preg_match("/\.$ext$/i", $displayname)) return $_type;
                }
        }
-
        return $type;
 }
 
-// ¥¢¥Ã¥×¥í¡¼¥É¥Õ¥©¡¼¥à¤Î½ÐÎÏ
+// アップロードフォームの出力
 function attach_form($page)
 {
        global $script, $vars, $_attach_messages;
 
        $r_page = rawurlencode($page);
-       $s_page = htmlspecialchars($page);
+       $s_page = htmlsc($page);
        $navi = <<<EOD
   <span class="small">
    [<a href="$script?plugin=attach&amp;pcmd=list&amp;refer=$r_page">{$_attach_messages['msg_list']}</a>]
@@ -377,8 +421,8 @@ EOD;
 EOD;
 }
 
-//-------- ¥¯¥é¥¹
-// ¥Õ¥¡¥¤¥ë
+//-------- ã\82¯ã\83©ã\82¹
+// ファイル
 class AttachFile
 {
        var $page, $file, $age, $basename, $filename, $logname;
@@ -399,15 +443,17 @@ class AttachFile
                $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) : '';
        }
 
-       // ¥Õ¥¡¥¤¥ë¾ðÊó¼èÆÀ
-       function getstatus()
+       function gethash()
        {
-               if (! $this->exist) return FALSE;
+               return $this->exist ? md5_file($this->filename) : '';
+       }
 
-               // ¥í¥°¥Õ¥¡¥¤¥ë¼èÆÀ
+       // ファイル情報取得
+       function getstatus()
+       {
+               // ログファイル取得
                if (file_exists($this->logname)) {
                        $data = file($this->logname);
                        foreach ($this->status as $key=>$value) {
@@ -415,15 +461,15 @@ class AttachFile
                        }
                        $this->status['count'] = explode(',', $this->status['count']);
                }
+               if (! $this->exist) return FALSE;
                $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/1024, 1)) . 'KB';
-               $this->type     = attach_mime_content_type($this->filename);
-
+               $this->type     = attach_mime_content_type($this->filename, $this->file);
                return TRUE;
        }
 
-       // ¥¹¥Æ¡¼¥¿¥¹Êݸ
+       // ステータス保存
        function putstatus()
        {
                $this->status['count'] = join(',', $this->status['count']);
@@ -439,7 +485,7 @@ class AttachFile
                fclose($fp);
        }
 
-       // ÆüÉÕ¤ÎÈæ³Ó´Ø¿ô
+       // 日付の比較関数
        function datecomp($a, $b) {
                return ($a->time == $b->time) ? 0 : (($a->time > $b->time) ? -1 : 1);
        }
@@ -452,7 +498,7 @@ class AttachFile
                $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 ? PLUGIN_ATTACH_FILE_ICON : '') . htmlspecialchars($this->file);
+               $label = ($showicon ? PLUGIN_ATTACH_FILE_ICON : '') . htmlsc($this->file);
                if ($this->age) {
                        $label .= ' (backup No.' . $this->age . ')';
                }
@@ -466,16 +512,17 @@ class AttachFile
                return "<a href=\"$script?plugin=attach&amp;pcmd=open$param\" title=\"$title\">$label</a>$count$info";
        }
 
-       // ¾ðÊóɽ¼¨
+       // 情報表示
        function info($err)
        {
                global $script, $_attach_messages;
 
                $r_page = rawurlencode($this->page);
-               $s_page = htmlspecialchars($this->page);
-               $s_file = htmlspecialchars($this->file);
+               $s_page = htmlsc($this->page);
+               $s_file = htmlsc($this->file);
                $s_err = ($err == '') ? '' : '<p style="font-weight:bold">' . $_attach_messages[$err] . '</p>';
 
+               $msg_rename  = '';
                if ($this->age) {
                        $msg_freezed = '';
                        $msg_delete  = '<input type="radio" name="pcmd" id="_p_attach_delete" value="delete" />' .
@@ -499,11 +546,22 @@ class AttachFile
                                $msg_freeze  = '<input type="radio" name="pcmd" id="_p_attach_freeze" value="freeze" />' .
                                        '<label for="_p_attach_freeze">' .  $_attach_messages['msg_freeze'] .
                                        $_attach_messages['msg_require'] . '</label><br />';
+
+                               if (PLUGIN_ATTACH_RENAME_ENABLE) {
+                                       $msg_rename  = '<input type="radio" name="pcmd" id="_p_attach_rename" value="rename" />' .
+                                               '<label for="_p_attach_rename">' .  $_attach_messages['msg_rename'] .
+                                               $_attach_messages['msg_require'] . '</label><br />&nbsp;&nbsp;&nbsp;&nbsp;' .
+                                               '<label for="_p_attach_newname">' . $_attach_messages['msg_newname'] .
+                                               ':</label> ' .
+                                               '<input type="text" name="newname" id="_p_attach_newname" size="40" value="' .
+                                               $this->file . '" /><br />';
+                               }
                        }
                }
                $info = $this->toString(TRUE, FALSE);
+               $hash = $this->gethash();
 
-               $retval = array('msg'=>sprintf($_attach_messages['msg_info'], htmlspecialchars($this->file)));
+               $retval = array('msg'=>sprintf($_attach_messages['msg_info'], htmlsc($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>]
@@ -513,7 +571,7 @@ class AttachFile
  <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_md5hash']}:$hash</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>
@@ -530,6 +588,8 @@ $s_err
   <input type="hidden" name="age" value="{$this->age}" />
   $msg_delete
   $msg_freeze
+  $msg_rename
+  <br />
   <label for="_p_attach_password">{$_attach_messages['msg_password']}:</label>
   <input type="password" name="pass" id="_p_attach_password" size="8" />
   <input type="submit" value="{$_attach_messages['btn_submit']}" />
@@ -541,7 +601,7 @@ EOD;
 
        function delete($pass)
        {
-               global $_attach_messages;
+               global $_attach_messages, $notify, $notify_subject;
 
                if ($this->status['freeze']) return attach_info('msg_isfreeze');
 
@@ -549,12 +609,12 @@ EOD;
                        if (PLUGIN_ATTACH_DELETE_ADMIN_ONLY || $this->age) {
                                return attach_info('err_adminpass');
                        } else if (PLUGIN_ATTACH_PASSWORD_REQUIRE &&
-                               md5($pass) != $this->status['pass']) {
+                               md5($pass) !== $this->status['pass']) {
                                return attach_info('err_password');
                        }
                }
 
-               // ¥Ð¥Ã¥¯¥¢¥Ã¥×
+               // バックアップ
                if ($this->age ||
                        (PLUGIN_ATTACH_DELETE_ADMIN_ONLY && PLUGIN_ATTACH_DELETE_ADMIN_NOBACKUP)) {
                        @unlink($this->filename);
@@ -564,7 +624,7 @@ EOD;
                        } while (file_exists($this->basename . '.' . $age));
 
                        if (! rename($this->basename,$this->basename . '.' . $age)) {
-                               // ºï½ü¼ºÇÔ why?
+                               // 削除失敗 why?
                                return array('msg'=>$_attach_messages['err_delete']);
                        }
 
@@ -576,9 +636,73 @@ EOD;
                if (is_page($this->page))
                        touch(get_filename($this->page));
 
+               if ($notify) {
+                       $footer['ACTION']   = 'File deleted';
+                       $footer['FILENAME'] = & $this->file;
+                       $footer['PAGE']     = & $this->page;
+                       $footer['URI']      = get_script_uri() .
+                               '?' . pagename_urlencode($this->page);
+                       $footer['USER_AGENT']  = TRUE;
+                       $footer['REMOTE_ADDR'] = TRUE;
+                       pkwk_mail_notify($notify_subject, "\n", $footer) or
+                               die('pkwk_mail_notify(): Failed');
+               }
+
                return array('msg'=>$_attach_messages['msg_deleted']);
        }
 
+       function rename($pass, $newname)
+       {
+               global $_attach_messages, $notify, $notify_subject;
+
+               if ($this->status['freeze']) return attach_info('msg_isfreeze');
+
+               if (! pkwk_login($pass)) {
+                       if (PLUGIN_ATTACH_DELETE_ADMIN_ONLY || $this->age) {
+                               return attach_info('err_adminpass');
+                       } else if (PLUGIN_ATTACH_PASSWORD_REQUIRE &&
+                               md5($pass) !== $this->status['pass']) {
+                               return attach_info('err_password');
+                       }
+               }
+               $newbase = UPLOAD_DIR . encode($this->page) . '_' . encode($newname);
+               if (file_exists($newbase)) {
+                       return array('msg'=>$_attach_messages['err_exists']);
+               }
+               if (! PLUGIN_ATTACH_RENAME_ENABLE) {
+                       return array('msg'=>$_attach_messages['err_rename']);
+               }
+               if (! rename($this->basename, $newbase)) {
+                       return array('msg'=>$_attach_messages['err_rename']);
+               }
+               // Rename primary file succeeded.
+               // Then, rename backup(archive) files and log file)
+               $rename_targets = array();
+               $dir = opendir(UPLOAD_DIR);
+               if ($dir) {
+                       $matches_leaf = array();
+                       if (preg_match('/(((?:[0-9A-F]{2})+)_((?:[0-9A-F]{2})+))$/', $this->basename, $matches_leaf)) {
+                               $attachfile_leafname = $matches_leaf[1];
+                               $attachfile_leafname_pattern = preg_quote($attachfile_leafname, '/');
+                               $pattern = "/^({$attachfile_leafname_pattern})(\.((\d+)|(log)))$/";
+                               $matches = array();
+                               while ($file = readdir($dir)) {
+                                       if (! preg_match($pattern, $file, $matches))
+                                               continue;
+                                       $basename2 = $matches[0];
+                                       $newbase2 = $newbase . $matches[2];
+                                       $rename_targets[$basename2] = $newbase2;
+                               }
+                       }
+                       closedir($dir);
+               }
+               foreach ($rename_targets as $basename2=>$newbase2) {
+                       $basename2path = UPLOAD_DIR . $basename2;
+                       rename($basename2path, $newbase2);
+               }
+               return array('msg'=>$_attach_messages['msg_renamed']);
+       }
+
        function freeze($freeze, $pass)
        {
                global $_attach_messages;
@@ -600,24 +724,22 @@ EOD;
                $filename = $this->file;
 
                // Care for Japanese-character-included file name
+               $legacy_filename = mb_convert_encoding($filename, 'UTF-8', SOURCE_ENCODING);
                if (LANG == 'ja') {
                        switch(UA_NAME . '/' . UA_PROFILE){
-                       case 'Opera/default':
-                               // Care for using _auto-encode-detecting_ function
-                               $filename = mb_convert_encoding($filename, 'UTF-8', 'auto');
-                               break;
                        case 'MSIE/default':
-                               $filename = mb_convert_encoding($filename, 'SJIS', 'auto');
+                               $legacy_filename = mb_convert_encoding($filename, 'SJIS', SOURCE_ENCODING);
                                break;
                        }
                }
-               $filename = htmlspecialchars($filename);
+               $utf8filename = mb_convert_encoding($filename, 'UTF-8', SOURCE_ENCODING);
 
                ini_set('default_charset', '');
                mb_http_output('pass');
 
                pkwk_common_headers();
-               header('Content-Disposition: inline; filename="' . $filename . '"');
+               header('Content-Disposition: inline; filename="' . $legacy_filename
+                       . '"; filename*=utf-8\'\'' . rawurlencode($utf8filename));
                header('Content-Length: ' . $this->size);
                header('Content-Type: '   . $this->type);
 
@@ -626,7 +748,7 @@ EOD;
        }
 }
 
-// ¥Õ¥¡¥¤¥ë¥³¥ó¥Æ¥Ê
+// ファイルコンテナ
 class AttachFiles
 {
        var $page;
@@ -639,10 +761,10 @@ class AttachFiles
 
        function add($file, $age)
        {
-               $this->files[$file][$age] = new AttachFile($this->page, $file, $age);
+               $this->files[$file][$age] = new AttachFile($this->page, $file, $age);
        }
 
-       // ¥Õ¥¡¥¤¥ë°ìÍ÷¤ò¼èÆÀ
+       // ファイル一覧を取得
        function toString($flat)
        {
                global $_title_cannotread;
@@ -655,7 +777,7 @@ class AttachFiles
 
                $ret = '';
                $files = array_keys($this->files);
-               sort($files);
+               sort($files, SORT_STRING);
 
                foreach ($files as $file) {
                        $_files = array();
@@ -663,9 +785,9 @@ class AttachFiles
                                $_files[$age] = $this->files[$file][$age]->toString(FALSE, TRUE);
                        }
                        if (! isset($_files[0])) {
-                               $_files[0] = htmlspecialchars($file);
+                               $_files[0] = htmlsc($file);
                        }
-                       ksort($_files);
+                       ksort($_files, SORT_NUMERIC);
                        $_file = $_files[0];
                        unset($_files[0]);
                        $ret .= " <li>$_file\n";
@@ -677,7 +799,7 @@ class AttachFiles
                return make_pagelink($this->page) . "\n<ul>\n$ret</ul>\n";
        }
 
-       // ¥Õ¥¡¥¤¥ë°ìÍ÷¤ò¼èÆÀ(inline)
+       // ファイル一覧を取得(inline)
        function to_flat()
        {
                $ret = '';
@@ -696,7 +818,7 @@ class AttachFiles
        }
 }
 
-// ¥Ú¡¼¥¸¥³¥ó¥Æ¥Ê
+// ページコンテナ
 class AttachPages
 {
        var $pages = array();
@@ -713,15 +835,14 @@ class AttachPages
                $pattern = "/^({$page_pattern})_((?:[0-9A-F]{2})+){$age_pattern}$/";
 
                $matches = array();
-               while ($file = readdir($dir)) {
-                       if (! preg_match($pattern, $file, $matches))
-                               continue;
+               while (($file = readdir($dir)) !== FALSE) {
+                       if (! preg_match($pattern, $file, $matches)) continue;
 
                        $_page = decode($matches[1]);
                        $_file = decode($matches[2]);
                        $_age  = isset($matches[3]) ? $matches[3] : 0;
                        if (! isset($this->pages[$_page])) {
-                               $this->pages[$_page] = new AttachFiles($_page);
+                               $this->pages[$_page] = new AttachFiles($_page);
                        }
                        $this->pages[$_page]->add($_file, $_age);
                }
@@ -730,8 +851,6 @@ class AttachPages
 
        function toString($page = '', $flat = FALSE)
        {
-               global $non_list;
-
                if ($page != '') {
                        if (! isset($this->pages[$page])) {
                                return '';
@@ -742,14 +861,12 @@ class AttachPages
                $ret = '';
 
                $pages = array_keys($this->pages);
-               sort($pages);
+               sort($pages, SORT_STRING);
 
-               $non_list_pattern = '/' . $non_list . '/';
                foreach ($pages as $page) {
-                       if (preg_match($non_list_pattern, $page)) continue;
-                       $ret .= '<li>' . $this->pages[$page]->toString($flat) . "</li>\n";
+                       if (check_non_list($page)) continue;
+                       $ret .= '<li>' . $this->pages[$page]->toString($flat) . '</li>' . "\n";
                }
                return "\n" . '<ul>' . "\n" . $ret . '</ul>' . "\n";
        }
 }
-?>