OSDN Git Service

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