2 /////////////////////////////////////////////////
3 // PukiWiki - Yet another WikiWikiWeb clone.
5 // $Id: attach.inc.php,v 1.31 2003/07/27 14:15:29 arino Exp $
11 changed by Y.MASUI <masui@hisec.co.jp> http://masui.net/pukiwiki/
12 modified by PANDA <panda@arino.jp> http://home.arino.jp/
15 // upload dir(must set end of /)
16 if (!defined('UPLOAD_DIR'))
18 define('UPLOAD_DIR','./attach/');
21 // max file size for upload on PHP(PHP default 2MB)
22 ini_set('upload_max_filesize','2M');
24 // max file size for upload on script of PukiWiki(default 1MB)
25 define('MAX_FILESIZE',1000000);
27 // ´ÉÍý¼Ô¤À¤±¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤ò¥¢¥Ã¥×¥í¡¼¥É¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë
28 define('ATTACH_UPLOAD_ADMIN_ONLY',FALSE); // FALSE or TRUE
29 // ´ÉÍý¼Ô¤À¤±¤¬ÅºÉÕ¥Õ¥¡¥¤¥ë¤òºï½ü¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë
30 define('ATTACH_DELETE_ADMIN_ONLY',FALSE); // FALSE or TRUE
32 // ¥¢¥Ã¥×¥í¡¼¥É/ºï½ü»þ¤Ë¥Ñ¥¹¥ï¡¼¥É¤òÍ׵᤹¤ë(ADMIN_ONLY¤¬Í¥Àè)
33 define('ATTACH_PASSWORD_REQUIRE',FALSE); // FALSE or TRUE
36 if (!defined('FILE_ICON'))
38 define('FILE_ICON','<img src="./image/file.png" width="20" height="20" alt="file" style="border-width:0px" />');
41 // mime-type¤òµ½Ò¤·¤¿¥Ú¡¼¥¸
42 define('ATTACH_CONFIG_PAGE_MIME','plugin/attach/mime-type');
45 function plugin_attach_convert()
49 if (!ini_get('file_uploads'))
51 return 'file_uploads disabled';
54 $nolist = $noform = FALSE;
56 if (func_num_args() > 0)
58 foreach (func_get_args() as $arg)
60 $arg = strtolower($arg);
61 $nolist |= ($arg == 'nolist');
62 $noform |= ($arg == 'noform');
68 $obj = &new AttachPages($vars['page']);
69 $ret .= $obj->toString($vars['page'],TRUE);
73 $ret .= attach_form($vars['page']);
80 function plugin_attach_action()
84 if (array_key_exists('openfile',$vars))
86 $vars['pcmd'] = 'open';
87 $vars['file'] = $vars['openfile'];
89 if (array_key_exists('delfile',$vars))
91 $vars['pcmd'] = 'delete';
92 $vars['file'] = $vars['delfile'];
94 if (array_key_exists('attach_file',$_FILES))
96 $pass = array_key_exists('pass',$vars) ? md5($vars['pass']) : NULL;
97 return attach_upload($_FILES['attach_file'],$vars['refer'],$pass);
100 $age = array_key_exists('age',$vars) ? $vars['age'] : 0;
101 $pcmd = array_key_exists('pcmd',$vars) ? $vars['pcmd'] : '';
105 case 'info': return attach_info();
106 case 'delete': return attach_delete();
107 case 'open': return attach_open();
108 case 'list': return attach_list();
109 case 'freeze': return attach_freeze(TRUE);
110 case 'unfreeze':return attach_freeze(FALSE);
111 case 'upload': return attach_showform();
113 if ($vars['page'] == '' or !is_page($vars['page']))
115 return attach_list();
118 return attach_showform();
120 //-------- call from skin
121 function attach_filelist()
123 global $vars,$_attach_messages;
125 $obj = &new AttachPages($vars['page'],0);
127 if (!array_key_exists($vars['page'],$obj->pages))
131 return $_attach_messages['msg_file'].': '.$obj->toString($vars['page'],TRUE)."\n";
134 //¥Õ¥¡¥¤¥ë¥¢¥Ã¥×¥í¡¼¥É
135 function attach_upload($file,$page,$pass=NULL)
137 // $pass=NULL : ¥Ñ¥¹¥ï¡¼¥É¤¬»ØÄꤵ¤ì¤Æ¤¤¤Ê¤¤
138 // $pass=TRUE : ¥¢¥Ã¥×¥í¡¼¥Éµö²Ä
139 global $adminpass,$_attach_messages;
141 if ($file['tmp_name'] == '' or !is_uploaded_file($file['tmp_name']))
143 return array('result'=>FALSE);
145 if ($file['size'] > MAX_FILESIZE)
147 return array('result'=>FALSE,'msg'=>$_attach_messages['err_exceed']);
149 if (!is_pagename($page) or ($pass !== TRUE and !is_editable($page)))
151 return array('result'=>FALSE,'msg'=>$_attach_messages['err_noparm']);
153 if (ATTACH_UPLOAD_ADMIN_ONLY and $pass !== TRUE
154 and ($pass === NULL or $pass != $adminpass))
156 return array('result'=>FALSE,'msg'=>$_attach_messages['err_adminpass']);
159 $obj = &new AttachFile($page,$file['name']);
163 return array('result'=>FALSE,'msg'=>$_attach_messages['err_exists']);
165 move_uploaded_file($file['tmp_name'],$obj->filename);
169 touch(get_filename($page));
173 $obj->status['pass'] = ($pass !== TRUE and $pass !== NULL) ? $pass : '';
176 return array('result'=>TRUE,'msg'=>$_attach_messages['msg_uploaded']);;
179 function attach_info($err='')
181 global $vars,$_attach_messages;
183 foreach (array('refer','file','age') as $var)
185 $$var = array_key_exists($var,$vars) ? $vars[$var] : '';
188 $obj = &new AttachFile($refer,$file,$age);
189 return $obj->getstatus() ? $obj->info($err) : array('msg'=>$_attach_messages['err_notfound']);
192 function attach_delete()
194 global $vars,$_attach_messages;
196 foreach (array('refer','file','age','pass') as $var)
198 $$var = array_key_exists($var,$vars) ? $vars[$var] : '';
201 if (is_freeze($refer) or !is_editable($refer))
203 return array('msg'=>$_attach_messages['err_noparm']);
206 $obj = &new AttachFile($refer,$file,$age);
207 return $obj->getstatus() ? $obj->delete($pass) : array('msg'=>$_attach_messages['err_notfound']);
210 function attach_freeze($freeze)
212 global $vars,$_attach_messages;
214 foreach (array('refer','file','age','pass') as $var)
216 $$var = array_key_exists($var,$vars) ? $vars[$var] : '';
219 if (is_freeze($refer) or !is_editable($refer))
221 return array('msg'=>$_attach_messages['err_noparm']);
224 $obj = &new AttachFile($refer,$file,$age);
225 return $obj->getstatus() ? $obj->freeze($freeze,$pass) : array('msg'=>$_attach_messages['err_notfound']);
228 function attach_open()
230 global $vars,$_attach_messages;
232 foreach (array('refer','file','age') as $var)
234 $$var = array_key_exists($var,$vars) ? $vars[$var] : '';
237 $obj = &new AttachFile($refer,$file,$age);
238 return $obj->getstatus() ? $obj->open() : array('msg'=>$_attach_messages['err_notfound']);
241 function attach_list()
244 global $_attach_messages;
246 $refer = array_key_exists('refer',$vars) ? $vars['refer'] : '';
248 $obj = &new AttachPages($refer);
250 $msg = $_attach_messages[$refer == '' ? 'msg_listall' : 'msg_listpage'];
251 $body = ($refer == '' or array_key_exists($refer,$obj->pages)) ?
252 $obj->toString($refer,FALSE) :
253 $_attach_messages['err_noexist'];
254 return array('msg'=>$msg,'body'=>$body);
256 //¥¢¥Ã¥×¥í¡¼¥É¥Õ¥©¡¼¥à¤òɽ¼¨
257 function attach_showform()
260 global $_attach_messages;
262 $vars['refer'] = $vars['page'];
263 $body = ini_get('file_uploads') ? attach_form($vars['page']) : 'file_uploads disabled.';
265 return array('msg'=>$_attach_messages['msg_upload'],'body'=>$body);
270 function attach_mime_content_type($filename)
272 $type = 'application/octet-stream'; //default
274 if (!file_exists($filename))
278 $size = @getimagesize($filename);
290 return 'application/x-shockwave-flash';
294 if (!preg_match('/_([0-9A-Z]+)$/',$filename,$matches))
298 $filename = decode($matches[1]);
300 // mime-type°ìÍ÷ɽ¤ò¼èÆÀ
301 $config = new Config(ATTACH_CONFIG_PAGE_MIME);
302 $table = $config->read() ? $config->get('mime-type') : array();
303 unset($config); // ¥á¥â¥êÀáÌó
305 foreach ($table as $row)
307 $_type = trim($row[0]);
308 $exts = preg_split('/\s+|,/',trim($row[1]),-1,PREG_SPLIT_NO_EMPTY);
310 foreach ($exts as $ext)
312 if (preg_match("/\.$ext$/i",$filename))
321 //¥¢¥Ã¥×¥í¡¼¥É¥Õ¥©¡¼¥à
322 function attach_form($page)
324 global $script,$vars;
325 global $_attach_messages;
327 $r_page = rawurlencode($page);
328 $s_page = htmlspecialchars($page);
331 [<a href="$script?plugin=attach&pcmd=list&refer=$r_page">{$_attach_messages['msg_list']}</a>]
332 [<a href="$script?plugin=attach&pcmd=list">{$_attach_messages['msg_listall']}</a>]
336 if (!(bool)ini_get('file_uploads'))
341 $maxsize = MAX_FILESIZE;
342 $msg_maxsize = sprintf($_attach_messages['msg_maxsize'],number_format($maxsize/1000)."KB");
345 if (ATTACH_PASSWORD_REQUIRE or ATTACH_UPLOAD_ADMIN_ONLY)
347 $title = $_attach_messages[ATTACH_UPLOAD_ADMIN_ONLY ? 'msg_adminpass' : 'msg_password'];
348 $pass = '<br />'.$title.': <input type="password" name="pass" size="8" />';
351 <form enctype="multipart/form-data" action="$script" method="post">
353 <input type="hidden" name="plugin" value="attach" />
354 <input type="hidden" name="pcmd" value="post" />
355 <input type="hidden" name="refer" value="$s_page" />
356 <input type="hidden" name="max_file_size" value="$maxsize" />
361 {$_attach_messages['msg_file']}: <input type="file" name="attach_file" />
363 <input type="submit" value="{$_attach_messages['btn_upload']}" />
372 var $page,$file,$age,$basename,$filename,$logname;
377 var $status = array('count'=>array(0),'age'=>'','pass'=>'','freeze'=>FALSE);
379 function AttachFile($page,$file,$age=0)
382 $this->file = basename($file);
383 $this->age = is_numeric($age) ? $age : 0;
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) : '';
400 if (file_exists($this->logname))
402 $data = file($this->logname);
403 foreach ($this->status as $key=>$value)
405 $this->status[$key] = chop(array_shift($data));
407 $this->status['count'] = explode(',',$this->status['count']);
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)/1000,1).'KB';
412 $this->type = attach_mime_content_type($this->filename);
419 $this->status['count'] = join(',',$this->status['count']);
420 $fp = fopen($this->logname,'wb')
421 or die_message('cannot write '.$this->logname);
423 foreach ($this->status as $key=>$value)
425 fwrite($fp,$value."\n");
431 function datecomp($a,$b)
433 return ($a->time == $b->time) ? 0 : (($a->time > $b->time) ? -1 : 1);
435 function toString($showicon,$showinfo)
437 global $script,$date_format,$time_format,$weeklabels;
438 global $_attach_messages;
441 $param = '&file='.rawurlencode($this->file).'&refer='.rawurlencode($this->page).
442 ($this->age ? '&age='.$this->age : '');
443 $title = $this->time_str.' '.$this->size_str;
444 $label = ($showicon ? FILE_ICON : '').htmlspecialchars($this->file);
447 $label .= ' (backup No.'.$this->age.')';
452 $_title = str_replace('$1',rawurlencode($this->file),$_attach_messages['msg_info']);
453 $info = "\n<span class=\"small\">[<a href=\"$script?plugin=attach&pcmd=info$param\" title=\"$_title\">{$_attach_messages['btn_info']}</a>]</span>";
454 $count = ($showicon and !empty($this->status['count'][$this->age])) ?
455 sprintf($_attach_messages['msg_count'],$this->status['count'][$this->age]) : '';
457 return "<a href=\"$script?plugin=attach&pcmd=open$param\" title=\"$title\">$label</a>$count$info";
462 global $script,$_attach_messages;
464 $r_page = rawurlencode($this->page);
465 $s_page = htmlspecialchars($this->page);
466 $s_file = htmlspecialchars($this->file);
467 $s_err = ($err == '') ? '' : '<p style="font-weight:bold">'.$_attach_messages[$err].'</p>';
472 $msg_delete = '<input type="radio" name="pcmd" value="delete" />'.$_attach_messages['msg_delete'];
473 $msg_delete .= $_attach_messages['msg_require'];
474 $msg_delete .= '<br />';
479 if ($this->status['freeze'])
481 $msg_freezed = "<dd>{$_attach_messages['msg_isfreeze']}</dd>";
483 $msg_freeze = '<input type="radio" name="pcmd" value="unfreeze" />'.$_attach_messages['msg_unfreeze'];
484 $msg_freeze .= $_attach_messages['msg_require'].'<br />';
489 $msg_delete = '<input type="radio" name="pcmd" value="delete" />'.$_attach_messages['msg_delete'];
490 if (ATTACH_DELETE_ADMIN_ONLY or $this->age)
492 $msg_delete .= $_attach_messages['msg_require'];
494 $msg_delete .= '<br />';
495 $msg_freeze = '<input type="radio" name="pcmd" value="freeze" />'.$_attach_messages['msg_freeze'];
496 $msg_freeze .= "{$_attach_messages['msg_require']}<br />";
499 $info = $this->toString(TRUE,FALSE);
501 $retval = array('msg'=>sprintf($_attach_messages['msg_info'],htmlspecialchars($this->file)));
502 $retval['body'] = <<< EOD
504 [<a href="$script?plugin=attach&pcmd=list&refer=$r_page">{$_attach_messages['msg_list']}</a>]
505 [<a href="$script?plugin=attach&pcmd=list">{$_attach_messages['msg_listall']}</a>]
509 <dd>{$_attach_messages['msg_page']}:$s_page</dd>
510 <dd>{$_attach_messages['msg_filename']}:{$this->filename}</dd>
511 <dd>{$_attach_messages['msg_md5hash']}:{$this->md5hash}</dd>
512 <dd>{$_attach_messages['msg_filesize']}:{$this->size_str} ({$this->size} bytes)</dd>
513 <dd>Content-type:{$this->type}</dd>
514 <dd>{$_attach_messages['msg_date']}:{$this->time_str}</dd>
515 <dd>{$_attach_messages['msg_dlcount']}:{$this->status['count'][$this->age]}</dd>
520 <form action="$script" method="post">
522 <input type="hidden" name="plugin" value="attach" />
523 <input type="hidden" name="refer" value="$s_page" />
524 <input type="hidden" name="file" value="$s_file" />
525 <input type="hidden" name="age" value="{$this->age}" />
528 {$_attach_messages['msg_password']}: <input type="password" name="pass" size="8" />
529 <input type="submit" value="{$_attach_messages['btn_submit']}" />
535 function delete($pass)
537 global $adminpass,$_attach_messages;
539 if ($this->status['freeze'])
541 return attach_info('msg_isfreeze');
544 if (md5($pass) != $adminpass)
546 if (ATTACH_DELETE_ADMIN_ONLY or $this->age)
548 return attach_info('err_adminpass');
550 else if (ATTACH_PASSWORD_REQUIRE and md5($pass) != $this->status['pass'])
552 return attach_info('err_password');
558 @unlink($this->filename);
564 $age = ++$this->status['age'];
566 while (file_exists($this->basename.'.'.$age));
568 if (!rename($this->basename,$this->basename.'.'.$age))
571 return array('msg'=>$_attach_messages['err_delete']);
574 $this->status['count'][$age] = $this->status['count'][0];
575 $this->status['count'][0] = 0;
578 if (is_page($this->page))
580 touch(get_filename($this->page));
583 return array('msg'=>$_attach_messages['msg_deleted']);
585 function freeze($freeze,$pass)
589 if (md5($pass) != $adminpass)
591 return attach_info('err_adminpass');
595 $this->status['freeze'] = $freeze;
598 return array('msg'=>$_attach_messages[$freeze ? 'msg_freezed' : 'msg_unfreezed']);
603 $this->status['count'][$this->age]++;
606 // for japanese (???)
607 $filename = htmlspecialchars(mb_convert_encoding($this->file,'SJIS','auto'));
608 header('Content-Disposition: inline; filename="'.$filename.'"');
609 header('Content-Length: '.$this->size);
610 header('Content-Type: '.$this->type);
611 @readfile($this->filename);
620 var $files = array();
622 function AttachFiles($page)
626 function add($file,$age)
628 $this->files[$file][$age] = &new AttachFile($this->page,$file,$age);
630 // ¥Õ¥¡¥¤¥ë°ìÍ÷¤ò¼èÆÀ
631 function toString($flat)
635 return $this->to_flat();
638 $files = array_keys($this->files);
640 foreach ($files as $file)
643 foreach (array_keys($this->files[$file]) as $age)
645 $_files[$age] = $this->files[$file][$age]->toString(FALSE,TRUE);
647 if (!array_key_exists(0,$_files))
649 $_files[0] = htmlspecialchars($file);
654 $ret .= " <li>$_file\n";
657 $ret .= "<ul>\n<li>".join("</li>\n<li>",$_files)."</li>\n</ul>\n";
661 return make_pagelink($this->page)."\n<ul>\n$ret</ul>\n";
663 // ¥Õ¥¡¥¤¥ë°ìÍ÷¤ò¼èÆÀ(inline)
668 foreach (array_keys($this->files) as $file)
670 if (array_key_exists(0,$this->files[$file]))
672 $files[$file] = &$this->files[$file][0];
675 uasort($files,array('AttachFile','datecomp'));
676 foreach (array_keys($files) as $file)
678 $ret .= $files[$file]->toString(TRUE,TRUE).' ';
687 var $pages = array();
689 function AttachPages($page='',$age=NULL)
692 $dir = opendir(UPLOAD_DIR)
693 or die('directory '.UPLOAD_DIR.' is not exist or not readable.');
695 $page_pattern = ($page == '') ? '(?:[0-9A-F]{2})+' : preg_quote(encode($page),'/');
696 $age_pattern = ($age === NULL) ?
697 '(?:\.([0-9]+))?' : ($age ? "\.($age)" : '');
698 $pattern = "/^({$page_pattern})_((?:[0-9A-F]{2})+){$age_pattern}$/";
700 while ($file = readdir($dir))
702 if (!preg_match($pattern,$file,$matches))
706 $_page = decode($matches[1]);
707 $_file = decode($matches[2]);
708 $_age = array_key_exists(3,$matches) ? $matches[3] : 0;
709 if (!array_key_exists($_page,$this->pages))
711 $this->pages[$_page] = &new AttachFiles($_page);
713 $this->pages[$_page]->add($_file,$_age);
717 function toString($page='',$flat=FALSE)
721 if (!array_key_exists($page,$this->pages))
725 return $this->pages[$page]->toString($flat);
728 $pages = array_keys($this->pages);
730 foreach ($pages as $page)
732 $ret .= '<li>'.$this->pages[$page]->toString($flat)."</li>\n";
734 return "\n<ul>\n".$ret."</ul>\n";