OSDN Git Service

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