OSDN Git Service

Cleanup/shrink a little about $non_list etc
[pukiwiki/pukiwiki.git] / plugin / attach.inc.php
1 <?php
2 /////////////////////////////////////////////////
3 // PukiWiki - Yet another WikiWikiWeb clone.
4 //
5 //  $Id: attach.inc.php,v 1.69 2005/01/09 08:12:21 henoheno Exp $
6 //
7
8 /*
9  ¥×¥é¥°¥¤¥ó attach
10
11  changed by Y.MASUI <masui@hisec.co.jp> http://masui.net/pukiwiki/
12  modified by PANDA <panda@arino.jp> http://home.arino.jp/
13 */
14
15 // Max file size for upload on PHP (PHP default: 2MB)
16 ini_set('upload_max_filesize', '2M');
17
18 // Max file size for upload on script of PukiWikiX_FILESIZE
19 define('PLUGIN_ATTACH_MAX_FILESIZE', (1024 * 1024)); // default: 1MB
20
21 // ´ÉÍý¼Ô¤À¤±¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤ò¥¢¥Ã¥×¥í¡¼¥É¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë
22 define('PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY', FALSE); // FALSE or TRUE
23
24 // ´ÉÍý¼Ô¤À¤±¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤òºï½ü¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë
25 define('PLUGIN_ATTACH_DELETE_ADMIN_ONLY', FALSE); // FALSE or TRUE
26
27 // ´ÉÍý¼Ô¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤òºï½ü¤¹¤ë¤È¤­¤Ï¡¢¥Ð¥Ã¥¯¥¢¥Ã¥×¤òºî¤é¤Ê¤¤
28 // PLUGIN_ATTACH_DELETE_ADMIN_ONLY=TRUE¤Î¤È¤­Í­¸ú
29 define('PLUGIN_ATTACH_DELETE_ADMIN_NOBACKUP', FALSE); // FALSE or TRUE
30
31 // ¥¢¥Ã¥×¥í¡¼¥É/ºï½ü»þ¤Ë¥Ñ¥¹¥ï¡¼¥É¤òÍ׵᤹¤ë(ADMIN_ONLY¤¬Í¥Àè)
32 define('PLUGIN_ATTACH_PASSWORD_REQUIRE', FALSE); // FALSE or TRUE
33
34 // ¥Õ¥¡¥¤¥ë¤Î¥¢¥¯¥»¥¹¸¢
35 define('PLUGIN_ATTACH_FILE_MODE', 0644);
36 //define('PLUGIN_ATTACH_FILE_MODE', 0604); // for XREA.COM
37
38 // File icon image
39 define('PLUGIN_ATTACH_FILE_ICON', '<img src="' . IMAGE_DIR .  'file.png"' .
40         ' width="20" height="20" alt="file"' .
41         ' style="border-width:0px" />');
42
43 // mime-type¤òµ­½Ò¤·¤¿¥Ú¡¼¥¸
44 define('PLUGIN_ATTACH_CONFIG_PAGE_MIME', 'plugin/attach/mime-type');
45
46 //-------- convert
47 function plugin_attach_convert()
48 {
49         global $vars;
50
51         $page = isset($vars['page']) ? $vars['page'] : '';
52
53         $nolist = $noform = FALSE;
54         if (func_num_args() > 0) {
55                 foreach (func_get_args() as $arg) {
56                         $arg = strtolower($arg);
57                         $nolist |= ($arg == 'nolist');
58                         $noform |= ($arg == 'noform');
59                 }
60         }
61
62         $ret = '';
63         if (! $nolist) {
64                 $obj  = & new AttachPages($page);
65                 $ret .= $obj->toString($page, TRUE);
66         }
67         if (! $noform) {
68                 $ret .= attach_form($page);
69         }
70
71         return $ret;
72 }
73
74 //-------- action
75 function plugin_attach_action()
76 {
77         global $vars, $_attach_messages;
78
79         // Backward compatible
80         if (isset($vars['openfile'])) {
81                 $vars['file'] = $vars['openfile'];
82                 $vars['pcmd'] = 'open';
83         }
84         if (isset($vars['delfile'])) {
85                 $vars['file'] = $vars['delfile'];
86                 $vars['pcmd'] = 'delete';
87         }
88
89         $pcmd  = isset($vars['pcmd'])  ? $vars['pcmd']  : '';
90         $refer = isset($vars['refer']) ? $vars['refer'] : '';
91         $pass  = isset($vars['pass'])  ? $vars['pass']  : NULL;
92         $page  = isset($vars['page'])  ? $vars['page']  : '';
93
94         if ($refer != '' && is_pagename($refer)) {
95                 if(in_array($pcmd, array('info', 'open', 'list'))) {
96                         check_readable($refer);
97                 } else {
98                         check_editable($refer);
99                 }
100         }
101
102         // Dispatch
103         if (isset($_FILES['attach_file'])) {
104                 // Upload
105                 return attach_upload($_FILES['attach_file'], $refer, $pass);
106         }
107         switch ($pcmd) {
108                 case 'info'     : return attach_info();
109                 case 'delete'   : return attach_delete();
110                 case 'open'     : return attach_open();
111                 case 'list'     : return attach_list();
112                 case 'freeze'   : return attach_freeze(TRUE);
113                 case 'unfreeze' : return attach_freeze(FALSE);
114                 case 'upload'   : return attach_showform();
115         }
116         if ($page == '' || ! is_page($page)) {
117                 return attach_list();
118         } else {
119                 return attach_showform();
120         }
121 }
122
123 //-------- call from skin
124 function attach_filelist()
125 {
126         global $vars, $_attach_messages;
127
128         $page = isset($vars['page']) ? $vars['page'] : '';
129
130         $obj = & new AttachPages($page, 0);
131
132         if (! isset($obj->pages[$page])) {
133                 return '';
134         } else {
135                 return $_attach_messages['msg_file'] . ': ' .
136                 $obj->toString($page, TRUE) . "\n";
137         }
138 }
139
140 //-------- ¼ÂÂÎ
141 // ¥Õ¥¡¥¤¥ë¥¢¥Ã¥×¥í¡¼¥É
142 // $pass = NULL : ¥Ñ¥¹¥ï¡¼¥É¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤¤
143 // $pass = TRUE : ¥¢¥Ã¥×¥í¡¼¥Éµö²Ä
144 function attach_upload($file, $page, $pass = NULL)
145 {
146         global $_attach_messages;
147
148         if (! is_page($page)) {
149                 die_message("No such page");
150         } else if ($file['tmp_name'] == '' || ! is_uploaded_file($file['tmp_name'])) {
151                 return array('result'=>FALSE);
152         } else if ($file['size'] > PLUGIN_ATTACH_MAX_FILESIZE) {
153                 return array(
154                         'result'=>FALSE,
155                         'msg'=>$_attach_messages['err_exceed']);
156         } else if (! is_pagename($page) || ($pass !== TRUE && ! is_editable($page))) {
157                 return array(
158                         'result'=>FALSE,'
159                         msg'=>$_attach_messages['err_noparm']);
160         } else if (PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY && $pass !== TRUE &&
161                   ($pass === NULL || ! pkwk_login($pass))) {
162                 return array(
163                         'result'=>FALSE,
164                         'msg'=>$_attach_messages['err_adminpass']);
165         }
166
167         $obj = & new AttachFile($page, $file['name']);
168         if ($obj->exist) {
169                 return array('result'=>FALSE,
170                         'msg'=>$_attach_messages['err_exists']);
171         }
172
173         if (move_uploaded_file($file['tmp_name'], $obj->filename)) {
174                 chmod($obj->filename, PLUGIN_ATTACH_FILE_MODE);
175         }
176
177         if (is_page($page)) {
178                 touch(get_filename($page));
179         }
180
181         $obj->getstatus();
182         $obj->status['pass'] = ($pass !== TRUE && $pass !== NULL) ? md5($pass) : '';
183         $obj->putstatus();
184
185         return array(
186                 'result'=>TRUE,
187                 'msg'=>$_attach_messages['msg_uploaded']);
188 }
189
190 // ¾ÜºÙ¥Õ¥©¡¼¥à¤òɽ¼¨
191 function attach_info($err = '')
192 {
193         global $vars, $_attach_messages;
194
195         foreach (array('refer', 'file', 'age') as $var) {
196                 ${$var} = isset($vars[$var]) ? $vars[$var] : '';
197         }
198
199         $obj = & new AttachFile($refer, $file, $age);
200         return $obj->getstatus() ?
201                 $obj->info($err) :
202                 array('msg'=>$_attach_messages['err_notfound']);
203 }
204
205 // ºï½ü
206 function attach_delete()
207 {
208         global $vars, $_attach_messages;
209
210         foreach (array('refer', 'file', 'age', 'pass') as $var) {
211                 ${$var} = isset($vars[$var]) ? $vars[$var] : '';
212         }
213
214         if (is_freeze($refer) || ! is_editable($refer)) {
215                 return array('msg'=>$_attach_messages['err_noparm']);
216         } else {
217                 $obj = & new AttachFile($refer, $file, $age);
218                 return $obj->getstatus() ?
219                         $obj->delete($pass) :
220                         array('msg'=>$_attach_messages['err_notfound']);
221         }
222 }
223
224 // Åà·ë
225 function attach_freeze($freeze)
226 {
227         global $vars, $_attach_messages;
228
229         foreach (array('refer', 'file', 'age', 'pass') as $var) {
230                 ${$var} = isset($vars[$var]) ? $vars[$var] : '';
231         }
232
233         if (is_freeze($refer) || ! is_editable($refer)) {
234                 return array('msg'=>$_attach_messages['err_noparm']);
235         } else {
236                 $obj = & new AttachFile($refer, $file, $age);
237                 return $obj->getstatus() ?
238                         $obj->freeze($freeze, $pass) :
239                         array('msg'=>$_attach_messages['err_notfound']);
240         }
241 }
242
243 // ¥À¥¦¥ó¥í¡¼¥É
244 function attach_open()
245 {
246         global $vars, $_attach_messages;
247
248         foreach (array('refer', 'file', 'age') as $var) {
249                 ${$var} = isset($vars[$var]) ? $vars[$var] : '';
250         }
251
252         $obj = & new AttachFile($refer, $file, $age);
253         return $obj->getstatus() ?
254                 $obj->open() :
255                 array('msg'=>$_attach_messages['err_notfound']);
256 }
257
258 // °ìÍ÷¼èÆÀ
259 function attach_list()
260 {
261         global $vars, $_attach_messages;
262
263         $refer = isset($vars['refer']) ? $vars['refer'] : '';
264
265         $obj = & new AttachPages($refer);
266
267         $msg = $_attach_messages[($refer == '') ? 'msg_listall' : 'msg_listpage'];
268         $body = ($refer == '' || isset($obj->pages[$refer])) ?
269                 $obj->toString($refer, FALSE) :
270                 $_attach_messages['err_noexist'];
271
272         return array('msg'=>$msg, 'body'=>$body);
273 }
274
275 // ¥¢¥Ã¥×¥í¡¼¥É¥Õ¥©¡¼¥à¤òɽ¼¨ (action»þ)
276 function attach_showform()
277 {
278         global $vars, $_attach_messages;
279
280         $page = isset($vars['page']) ? $vars['page'] : '';
281         $vars['refer'] = $page;
282         $body = attach_form($page);
283
284         return array('msg'=>$_attach_messages['msg_upload'], 'body'=>$body);
285 }
286
287 //-------- ¥µ¡¼¥Ó¥¹
288 // mime-type¤Î·èÄê
289 function attach_mime_content_type($filename)
290 {
291         $type = 'application/octet-stream'; // default
292
293         if (! file_exists($filename)) return $type;
294
295         $size = @getimagesize($filename);
296         if (is_array($size)) {
297                 switch ($size[2]) {
298                         case 1: return 'image/gif';
299                         case 2: return 'image/jpeg';
300                         case 3: return 'image/png';
301                         case 4: return 'application/x-shockwave-flash';
302                 }
303         }
304
305         $matches = array();
306         if (! preg_match('/_((?:[0-9A-F]{2})+)(?:\.\d+)?$/', $filename, $matches))
307                 return $type;
308
309         $filename = decode($matches[1]);
310
311         // mime-type°ìÍ÷ɽ¤ò¼èÆÀ
312         $config = new Config(PLUGIN_ATTACH_CONFIG_PAGE_MIME);
313         $table = $config->read() ? $config->get('mime-type') : array();
314         unset($config); // ¥á¥â¥êÀáÌó
315
316         foreach ($table as $row) {
317                 $_type = trim($row[0]);
318                 $exts = preg_split('/\s+|,/', trim($row[1]), -1, PREG_SPLIT_NO_EMPTY);
319                 foreach ($exts as $ext) {
320                         if (preg_match("/\.$ext$/i", $filename)) return $_type;
321                 }
322         }
323
324         return $type;
325 }
326
327 // ¥¢¥Ã¥×¥í¡¼¥É¥Õ¥©¡¼¥à¤Î½ÐÎÏ
328 function attach_form($page)
329 {
330         global $script, $vars, $_attach_messages;
331
332         $r_page = rawurlencode($page);
333         $s_page = htmlspecialchars($page);
334         $navi = <<<EOD
335   <span class="small">
336    [<a href="$script?plugin=attach&amp;pcmd=list&amp;refer=$r_page">{$_attach_messages['msg_list']}</a>]
337    [<a href="$script?plugin=attach&amp;pcmd=list">{$_attach_messages['msg_listall']}</a>]
338   </span><br />
339 EOD;
340
341         if (! ini_get('file_uploads')) return '#attach(): file_uploads disabled<br />' . $navi;
342         if (! is_page($page))          return '#attach(): No such page<br />'          . $navi;
343
344         $maxsize = PLUGIN_ATTACH_MAX_FILESIZE;
345         $msg_maxsize = sprintf($_attach_messages['msg_maxsize'], number_format($maxsize/1024) . 'KB');
346
347         $pass = '';
348         if (PLUGIN_ATTACH_PASSWORD_REQUIRE || PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY) {
349                 $title = $_attach_messages[PLUGIN_ATTACH_UPLOAD_ADMIN_ONLY ? 'msg_adminpass' : 'msg_password'];
350                 $pass = '<br />' . $title . ': <input type="password" name="pass" size="8" />';
351         }
352         return <<<EOD
353 <form enctype="multipart/form-data" action="$script" method="post">
354  <div>
355   <input type="hidden" name="plugin" value="attach" />
356   <input type="hidden" name="pcmd"   value="post" />
357   <input type="hidden" name="refer"  value="$s_page" />
358   <input type="hidden" name="max_file_size" value="$maxsize" />
359   $navi
360   <span class="small">
361    $msg_maxsize
362   </span><br />
363   {$_attach_messages['msg_file']}: <input type="file" name="attach_file" />
364   $pass
365   <input type="submit" value="{$_attach_messages['btn_upload']}" />
366  </div>
367 </form>
368 EOD;
369 }
370
371 //-------- ¥¯¥é¥¹
372 // ¥Õ¥¡¥¤¥ë
373 class AttachFile
374 {
375         var $page, $file, $age, $basename, $filename, $logname;
376         var $time = 0;
377         var $size = 0;
378         var $time_str = '';
379         var $size_str = '';
380         var $status = array('count'=>array(0), 'age'=>'', 'pass'=>'', 'freeze'=>FALSE);
381
382         function AttachFile($page, $file, $age = 0)
383         {
384                 $this->page = $page;
385                 $this->file = preg_replace('#^.*/#','',$file);
386                 $this->age  = is_numeric($age) ? $age : 0;
387
388                 $this->basename = UPLOAD_DIR . encode($page) . '_' . encode($this->file);
389                 $this->filename = $this->basename . ($age ? '.' . $age : '');
390                 $this->logname  = $this->basename . '.log';
391                 $this->exist    = file_exists($this->filename);
392                 $this->time     = $this->exist ? filemtime($this->filename) - LOCALZONE : 0;
393                 $this->md5hash  = $this->exist ? md5_file($this->filename) : '';
394         }
395
396         // ¥Õ¥¡¥¤¥ë¾ðÊó¼èÆÀ
397         function getstatus()
398         {
399                 if (! $this->exist) return FALSE;
400
401                 // ¥í¥°¥Õ¥¡¥¤¥ë¼èÆÀ
402                 if (file_exists($this->logname)) {
403                         $data = file($this->logname);
404                         foreach ($this->status as $key=>$value) {
405                                 $this->status[$key] = chop(array_shift($data));
406                         }
407                         $this->status['count'] = explode(',', $this->status['count']);
408                 }
409                 $this->time_str = get_date('Y/m/d H:i:s', $this->time);
410                 $this->size     = filesize($this->filename);
411                 $this->size_str = sprintf('%01.1f', round($this->size/1024, 1)) . 'KB';
412                 $this->type     = attach_mime_content_type($this->filename);
413
414                 return TRUE;
415         }
416
417         // ¥¹¥Æ¡¼¥¿¥¹Êݸ
418         function putstatus()
419         {
420                 $this->status['count'] = join(',', $this->status['count']);
421                 $fp = fopen($this->logname, 'wb') or
422                         die_message('cannot write ' . $this->logname);
423                 set_file_buffer($fp, 0);
424                 flock($fp, LOCK_EX);
425                 rewind($fp);
426                 foreach ($this->status as $key=>$value) {
427                         fwrite($fp, $value . "\n");
428                 }
429                 flock($fp, LOCK_UN);
430                 fclose($fp);
431         }
432
433         // ÆüÉÕ¤ÎÈæ³Ó´Ø¿ô
434         function datecomp($a, $b) {
435                 return ($a->time == $b->time) ? 0 : (($a->time > $b->time) ? -1 : 1);
436         }
437
438         function toString($showicon, $showinfo)
439         {
440                 global $script, $_attach_messages;
441
442                 $this->getstatus();
443                 $param  = '&amp;file=' . rawurlencode($this->file) . '&amp;refer=' . rawurlencode($this->page) .
444                         ($this->age ? '&amp;age=' . $this->age : '');
445                 $title = $this->time_str . ' ' . $this->size_str;
446                 $label = ($showicon ? PLUGIN_ATTACH_FILE_ICON : '') . htmlspecialchars($this->file);
447                 if ($this->age) {
448                         $label .= ' (backup No.' . $this->age . ')';
449                 }
450                 $info = $count = '';
451                 if ($showinfo) {
452                         $_title = str_replace('$1', rawurlencode($this->file), $_attach_messages['msg_info']);
453                         $info = "\n<span class=\"small\">[<a href=\"$script?plugin=attach&amp;pcmd=info$param\" title=\"$_title\">{$_attach_messages['btn_info']}</a>]</span>\n";
454                         $count = ($showicon && ! empty($this->status['count'][$this->age])) ?
455                                 sprintf($_attach_messages['msg_count'], $this->status['count'][$this->age]) : '';
456                 }
457                 return "<a href=\"$script?plugin=attach&amp;pcmd=open$param\" title=\"$title\">$label</a>$count$info";
458         }
459
460         // ¾ðÊóɽ¼¨
461         function info($err)
462         {
463                 global $script, $_attach_messages;
464
465                 $r_page = rawurlencode($this->page);
466                 $s_page = htmlspecialchars($this->page);
467                 $s_file = htmlspecialchars($this->file);
468                 $s_err = ($err == '') ? '' : '<p style="font-weight:bold">' . $_attach_messages[$err] . '</p>';
469
470                 if ($this->age) {
471                         $msg_freezed = '';
472                         $msg_delete  = '<input type="radio" name="pcmd" value="delete" />' .
473                                 $_attach_messages['msg_delete'] .
474                                 $_attach_messages['msg_require'] . '<br />';
475                         $msg_freeze  = '';
476                 } else {
477                         if ($this->status['freeze']) {
478                                 $msg_freezed = "<dd>{$_attach_messages['msg_isfreeze']}</dd>";
479                                 $msg_delete  = '';
480                                 $msg_freeze  = '<input type="radio" name="pcmd" value="unfreeze" />' .
481                                         $_attach_messages['msg_unfreeze'] .
482                                         $_attach_messages['msg_require'] . '<br />';
483                         } else {
484                                 $msg_freezed = '';
485                                 $msg_delete = '<input type="radio" name="pcmd" value="delete" />' .
486                                         $_attach_messages['msg_delete'];
487                                 if (PLUGIN_ATTACH_DELETE_ADMIN_ONLY || $this->age) {
488                                         $msg_delete .= $_attach_messages['msg_require'];
489                                 }
490                                 $msg_delete .= '<br />';
491                                 $msg_freeze  = '<input type="radio" name="pcmd" value="freeze" />' .
492                                         $_attach_messages['msg_freeze'] .
493                                         $_attach_messages['msg_require'] . '<br />';
494                         }
495                 }
496                 $info = $this->toString(TRUE, FALSE);
497
498                 $retval = array('msg'=>sprintf($_attach_messages['msg_info'], htmlspecialchars($this->file)));
499                 $retval['body'] = <<< EOD
500 <p class="small">
501  [<a href="$script?plugin=attach&amp;pcmd=list&amp;refer=$r_page">{$_attach_messages['msg_list']}</a>]
502  [<a href="$script?plugin=attach&amp;pcmd=list">{$_attach_messages['msg_listall']}</a>]
503 </p>
504 <dl>
505  <dt>$info</dt>
506  <dd>{$_attach_messages['msg_page']}:$s_page</dd>
507  <dd>{$_attach_messages['msg_filename']}:{$this->filename}</dd>
508  <dd>{$_attach_messages['msg_md5hash']}:{$this->md5hash}</dd>
509  <dd>{$_attach_messages['msg_filesize']}:{$this->size_str} ({$this->size} bytes)</dd>
510  <dd>Content-type:{$this->type}</dd>
511  <dd>{$_attach_messages['msg_date']}:{$this->time_str}</dd>
512  <dd>{$_attach_messages['msg_dlcount']}:{$this->status['count'][$this->age]}</dd>
513  $msg_freezed
514 </dl>
515 <hr />
516 $s_err
517 <form action="$script" method="post">
518  <div>
519   <input type="hidden" name="plugin" value="attach" />
520   <input type="hidden" name="refer" value="$s_page" />
521   <input type="hidden" name="file" value="$s_file" />
522   <input type="hidden" name="age" value="{$this->age}" />
523   $msg_delete
524   $msg_freeze
525   {$_attach_messages['msg_password']}: <input type="password" name="pass" size="8" />
526   <input type="submit" value="{$_attach_messages['btn_submit']}" />
527  </div>
528 </form>
529 EOD;
530                 return $retval;
531         }
532
533         function delete($pass)
534         {
535                 global $_attach_messages;
536
537                 if ($this->status['freeze']) return attach_info('msg_isfreeze');
538
539                 if (! pkwk_login($pass)) {
540                         if (PLUGIN_ATTACH_DELETE_ADMIN_ONLY || $this->age) {
541                                 return attach_info('err_adminpass');
542                         } else if (PLUGIN_ATTACH_PASSWORD_REQUIRE &&
543                                 md5($pass) != $this->status['pass']) {
544                                 return attach_info('err_password');
545                         }
546                 }
547
548                 // ¥Ð¥Ã¥¯¥¢¥Ã¥×
549                 if ($this->age ||
550                         (PLUGIN_ATTACH_DELETE_ADMIN_ONLY && PLUGIN_ATTACH_DELETE_ADMIN_NOBACKUP)) {
551                         @unlink($this->filename);
552                 } else {
553                         do {
554                                 $age = ++$this->status['age'];
555                         } while (file_exists($this->basename . '.' . $age));
556
557                         if (! rename($this->basename,$this->basename . '.' . $age)) {
558                                 // ºï½ü¼ºÇÔ why?
559                                 return array('msg'=>$_attach_messages['err_delete']);
560                         }
561
562                         $this->status['count'][$age] = $this->status['count'][0];
563                         $this->status['count'][0] = 0;
564                         $this->putstatus();
565                 }
566
567                 if (is_page($this->page)) {
568                         touch(get_filename($this->page));
569                 }
570
571                 return array('msg'=>$_attach_messages['msg_deleted']);
572         }
573
574         function freeze($freeze, $pass)
575         {
576                 global $_attach_messages;
577
578                 if (! pkwk_login($pass)) return attach_info('err_adminpass');
579
580                 $this->getstatus();
581                 $this->status['freeze'] = $freeze;
582                 $this->putstatus();
583
584                 return array('msg'=>$_attach_messages[$freeze ? 'msg_freezed' : 'msg_unfreezed']);
585         }
586
587         function open()
588         {
589                 $this->getstatus();
590                 $this->status['count'][$this->age]++;
591                 $this->putstatus();
592                 $filename = $this->file;
593
594                 // Care for Japanese-character-included file name
595                 if (LANG == 'ja') {
596                         switch(UA_NAME . '/' . UA_PROFILE){
597                         case 'Opera/default':
598                                 // Care for using _auto-encode-detecting_ function
599                                 $filename = mb_convert_encoding($filename, 'UTF-8', 'auto');
600                                 break;
601                         case 'MSIE/default':
602                                 $filename = mb_convert_encoding($filename, 'SJIS', 'auto');
603                                 break;
604                         }
605                 }
606                 $filename = htmlspecialchars($filename);
607
608                 ini_set('default_charset', '');
609                 mb_http_output('pass');
610
611                 pkwk_common_headers();
612                 header('Content-Disposition: inline; filename="' . $filename . '"');
613                 header('Content-Length: ' . $this->size);
614                 header('Content-Type: '   . $this->type);
615
616                 @readfile($this->filename);
617                 exit;
618         }
619 }
620
621 // ¥Õ¥¡¥¤¥ë¥³¥ó¥Æ¥Ê
622 class AttachFiles
623 {
624         var $page;
625         var $files = array();
626
627         function AttachFiles($page)
628         {
629                 $this->page = $page;
630         }
631
632         function add($file, $age)
633         {
634                 $this->files[$file][$age] = & new AttachFile($this->page, $file, $age);
635         }
636
637         // ¥Õ¥¡¥¤¥ë°ìÍ÷¤ò¼èÆÀ
638         function toString($flat)
639         {
640                 global $_title_cannotread;
641
642                 if (! check_readable($this->page, FALSE, FALSE)) {
643                         return str_replace('$1', make_pagelink($this->page), $_title_cannotread);
644                 } else if ($flat) {
645                         return $this->to_flat();
646                 }
647
648                 $ret = '';
649                 $files = array_keys($this->files);
650                 sort($files);
651
652                 foreach ($files as $file) {
653                         $_files = array();
654                         foreach (array_keys($this->files[$file]) as $age) {
655                                 $_files[$age] = $this->files[$file][$age]->toString(FALSE, TRUE);
656                         }
657                         if (! isset($_files[0])) {
658                                 $_files[0] = htmlspecialchars($file);
659                         }
660                         ksort($_files);
661                         $_file = $_files[0];
662                         unset($_files[0]);
663                         $ret .= " <li>$_file\n";
664                         if (count($_files)) {
665                                 $ret .= "<ul>\n<li>" . join("</li>\n<li>", $_files) . "</li>\n</ul>\n";
666                         }
667                         $ret .= " </li>\n";
668                 }
669                 return make_pagelink($this->page) . "\n<ul>\n$ret</ul>\n";
670         }
671
672         // ¥Õ¥¡¥¤¥ë°ìÍ÷¤ò¼èÆÀ(inline)
673         function to_flat()
674         {
675                 $ret = '';
676                 $files = array();
677                 foreach (array_keys($this->files) as $file) {
678                         if (isset($this->files[$file][0])) {
679                                 $files[$file] = & $this->files[$file][0];
680                         }
681                 }
682                 uasort($files, array('AttachFile', 'datecomp'));
683                 foreach (array_keys($files) as $file) {
684                         $ret .= $files[$file]->toString(TRUE, TRUE) . ' ';
685                 }
686
687                 return $ret;
688         }
689 }
690
691 // ¥Ú¡¼¥¸¥³¥ó¥Æ¥Ê
692 class AttachPages
693 {
694         var $pages = array();
695
696         function AttachPages($page = '', $age = NULL)
697         {
698
699                 $dir = opendir(UPLOAD_DIR) or
700                         die('directory ' . UPLOAD_DIR . ' is not exist or not readable.');
701
702                 $page_pattern = ($page == '') ? '(?:[0-9A-F]{2})+' : preg_quote(encode($page), '/');
703                 $age_pattern = ($age === NULL) ?
704                         '(?:\.([0-9]+))?' : ($age ?  "\.($age)" : '');
705                 $pattern = "/^({$page_pattern})_((?:[0-9A-F]{2})+){$age_pattern}$/";
706
707                 $matches = array();
708                 while ($file = readdir($dir)) {
709                         if (! preg_match($pattern, $file, $matches))
710                                 continue;
711
712                         $_page = decode($matches[1]);
713                         $_file = decode($matches[2]);
714                         $_age  = isset($matches[3]) ? $matches[3] : 0;
715                         if (! isset($this->pages[$_page])) {
716                                 $this->pages[$_page] = & new AttachFiles($_page);
717                         }
718                         $this->pages[$_page]->add($_file, $_age);
719                 }
720                 closedir($dir);
721         }
722
723         function toString($page = '', $flat = FALSE)
724         {
725                 global $non_list;
726
727                 if ($page != '') {
728                         if (! isset($this->pages[$page])) {
729                                 return '';
730                         } else {
731                                 return $this->pages[$page]->toString($flat);
732                         }
733                 }
734                 $ret = '';
735
736                 $pages = array_keys($this->pages);
737                 sort($pages);
738
739                 $non_list_pattern = '/' . $non_list . '/';
740                 foreach ($pages as $page) {
741                         if (preg_match($non_list_pattern, $page)) continue;
742                         $ret .= '<li>' . $this->pages[$page]->toString($flat) . "</li>\n";
743                 }
744                 return "\n" . '<ul>' . "\n" . $ret . '</ul>' . "\n";
745         }
746 }
747 ?>