upload.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. <?php if (!defined('PmWiki')) exit();
  2. /* Copyright 2004-2020 Patrick R. Michaud (pmichaud@pobox.com)
  3. This file is part of PmWiki; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published
  5. by the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version. See pmwiki.php for full details.
  7. This script adds upload capabilities to PmWiki. Uploads can be
  8. enabled by setting
  9. $EnableUpload = 1;
  10. in config.php. In addition, an upload password must be set, as
  11. the default is to lock uploads. In some configurations it may also
  12. be necessary to set values for $UploadDir and $UploadUrlFmt,
  13. especially if any form of URL rewriting is being performed.
  14. See the PmWiki.UploadsAdmin page for more information.
  15. Script maintained by Petko YOTOV www.pmwiki.org/petko
  16. */
  17. ## $EnableUploadOverwrite determines if we allow previously uploaded
  18. ## files to be overwritten.
  19. SDV($EnableUploadOverwrite,1);
  20. ## $UploadExts contains the list of file extensions we're willing to
  21. ## accept, along with the Content-Type: value appropriate for each.
  22. SDVA($UploadExts,array(
  23. 'gif' => 'image/gif', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg',
  24. 'png' => 'image/png', 'bmp' => 'image/bmp', 'ico' => 'image/x-icon',
  25. 'wbmp'=> 'image/vnd.wap.wbmp', 'xcf' => 'image/x-xcf', 'webp' => 'image/webp',
  26. 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml',
  27. 'mp3' => 'audio/mpeg', 'au' => 'audio/basic', 'wav' => 'audio/x-wav',
  28. 'ogg' => 'audio/ogg', 'flac' => 'audio/x-flac', 'opus' => 'audio/opus',
  29. 'ogv' => 'video/ogg', 'mp4' => 'video/mp4', 'webm' => 'video/webm',
  30. 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mkv' => 'video/x-matroska',
  31. 'm4v' => 'video/x-m4v', '3gp' => 'video/3gpp',
  32. 'mov' => 'video/quicktime', 'qt' => 'video/quicktime',
  33. 'wmf' => 'text/plain', 'avi' => 'video/x-msvideo',
  34. 'zip' => 'application/zip', '7z' => 'application/x-7z-compressed',
  35. 'gz' => 'application/x-gzip', 'tgz' => 'application/x-gzip',
  36. 'rpm' => 'application/x-rpm',
  37. 'hqx' => 'application/mac-binhex40', 'sit' => 'application/x-stuffit',
  38. 'doc' => 'application/msword', 'ppt' => 'application/vnd.ms-powerpoint',
  39. 'xls' => 'application/vnd.ms-excel', 'mdb' => 'text/plain',
  40. 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  41. 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  42. 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  43. 'exe' => 'application/octet-stream',
  44. 'pdf' => 'application/pdf', 'psd' => 'text/plain',
  45. 'ps' => 'application/postscript', 'ai' => 'application/postscript',
  46. 'eps' => 'application/postscript',
  47. 'htm' => 'text/html', 'html' => 'text/html', 'css' => 'text/css',
  48. 'fla' => 'application/x-shockwave-flash',
  49. 'swf' => 'application/x-shockwave-flash',
  50. 'txt' => 'text/plain', 'rtf' => 'application/rtf',
  51. 'tex' => 'application/x-tex', 'dvi' => 'application/x-dvi',
  52. 'odt' => 'application/vnd.oasis.opendocument.text',
  53. 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
  54. 'odp' => 'application/vnd.oasis.opendocument.presentation',
  55. 'odg' => 'application/vnd.oasis.opendocument.graphics',
  56. 'epub'=> 'application/epub+zip',
  57. 'kml' => 'application/vnd.google-earth.kml+xml',
  58. 'kmz' => 'application/vnd.google-earth.kmz',
  59. 'vtt' => 'text/vtt',
  60. '' => 'text/plain'));
  61. # Array containing forbidden strings in a filename, array('.php', '.cgi')
  62. SDV($UploadBlacklist, array());
  63. SDV($UploadMaxSize,50000);
  64. SDV($UploadPrefixQuota,0);
  65. SDV($UploadDirQuota,0);
  66. foreach($UploadExts as $k=>$v)
  67. if (!isset($UploadExtSize[$k])) $UploadExtSize[$k]=$UploadMaxSize;
  68. SDV($UploadDir,'uploads');
  69. SDV($UploadPermAdd,0444);
  70. SDV($UploadPermSet,0);
  71. SDV($UploadPrefixFmt,'/$Group');
  72. SDV($UploadFileFmt,"$UploadDir$UploadPrefixFmt");
  73. $v = preg_replace('#^/(.*/)#', '', $UploadDir);
  74. SDV($UploadUrlFmt,preg_replace('#/[^/]*$#', "/$v", $PubDirUrl, 1));
  75. SDV($LinkUploadCreateFmt, "<a rel='nofollow' class='createlinktext' href='\$LinkUpload'>\$LinkText</a><a rel='nofollow' class='createlink' href='\$LinkUpload'>&nbsp;&Delta;</a>");
  76. SDVA($ActionTitleFmt, array('upload' => '| $[Attach]'));
  77. if ($EnablePostAuthorRequired)
  78. SDV($EnableUploadAuthorRequired, $EnablePostAuthorRequired);
  79. SDV($PageUploadFmt,array("
  80. <div id='wikiupload'>
  81. <h2 class='wikiaction'>$[Attachments for] {\$FullName}</h2>
  82. <h3>\$UploadResult</h3>
  83. <form enctype='multipart/form-data' action='{\$PageUrl}?action=postupload' method='post'>
  84. <input type='hidden' name='n' value='{\$FullName}' />
  85. <input type='hidden' name='action' value='postupload' />
  86. <table border='0'>
  87. <tr><td align='right'>$[File to upload:]</td><td><input
  88. name='uploadfile' type='file' required='required' /></td></tr>
  89. <tr><td align='right'>$[Name attachment as:]</td>
  90. <td><input type='text' name='upname' value='\$UploadName' />
  91. </td></tr>
  92. <tr><td align='right'>$[Uploader]:</td>
  93. <td><input type='text' name='author' value='\$UploadAuthor' \$UploadAuthorRequired />
  94. <input type='submit' value=' $[Upload] ' />
  95. </td></tr></table></form></div>",
  96. 'wiki:$[{$SiteGroup}/UploadQuickReference]'));
  97. XLSDV('en',array(
  98. 'ULsuccess' => 'successfully uploaded',
  99. 'ULauthorrequired' => 'An author name is required.',
  100. 'ULbadname' => 'invalid attachment name',
  101. 'ULbadtype' => '\'$upext\' is not an allowed file extension',
  102. 'ULtoobig' => 'file is larger than maximum allowed by webserver',
  103. 'ULtoobigext' => 'file is larger than allowed maximum of $upmax
  104. bytes for \'$upext\' files',
  105. 'ULpartial' => 'incomplete file received',
  106. 'ULnofile' => 'no file uploaded',
  107. 'ULexists' => 'file with that name already exists',
  108. 'ULpquota' => 'group quota exceeded',
  109. 'ULtquota' => 'upload quota exceeded'));
  110. SDV($PageAttributes['passwdupload'],'$[Set new upload password:]');
  111. SDV($DefaultPasswords['upload'],'@lock');
  112. SDV($AuthCascade['upload'], 'read');
  113. SDV($FmtPV['$PasswdUpload'], 'PasswdVar($pn, "upload")');
  114. Markup('attachlist', 'directives',
  115. '/\\(:attachlist\\s*(.*?):\\)/i',
  116. "MarkupFmtUploadList");
  117. function MarkupFmtUploadList($m) {
  118. extract($GLOBALS["MarkupToHTML"]); # get $pagename
  119. return Keep('<ul>'.FmtUploadList($pagename,$m[1]).'</ul>');
  120. }
  121. SDV($GUIButtons['attach'], array(220, 'Attach:', '', '$[file.ext]',
  122. '$GUIButtonDirUrlFmt/attach.gif"$[Attach file]"'));
  123. SDV($LinkFunctions['Attach:'], 'LinkUpload');
  124. SDV($IMap['Attach:'], '$1');
  125. SDVA($HandleActions, array('upload' => 'HandleUpload',
  126. 'postupload' => 'HandlePostUpload',
  127. 'download' => 'HandleDownload'));
  128. SDVA($HandleAuth, array('upload' => 'upload',
  129. 'download' => 'read'));
  130. SDV($HandleAuth['postupload'], $HandleAuth['upload']);
  131. SDV($UploadVerifyFunction, 'UploadVerifyBasic');
  132. function MakeUploadName($pagename,$x) {
  133. global $UploadNameChars, $MakeUploadNamePatterns;
  134. SDV($UploadNameChars, "-\\w. ");
  135. SDV($MakeUploadNamePatterns, array(
  136. "/[^$UploadNameChars]/" => '',
  137. '/(\\.[^.]*)$/' => 'cb_tolower',
  138. '/^[^[:alnum:]_]+/' => '',
  139. '/[^[:alnum:]_]+$/' => ''));
  140. return PPRA($MakeUploadNamePatterns, $x);
  141. }
  142. function LinkUpload($pagename, $imap, $path, $alt, $txt, $fmt=NULL) {
  143. global $FmtV, $UploadFileFmt, $LinkUploadCreateFmt,
  144. $UploadUrlFmt, $UploadPrefixFmt, $EnableDirectDownload;
  145. if (preg_match('!^(.*)/([^/]+)$!', $path, $match)) {
  146. $pagename = MakePageName($pagename, $match[1]);
  147. $path = $match[2];
  148. }
  149. $upname = MakeUploadName($pagename, $path);
  150. $encname = rawurlencode($upname);
  151. $filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
  152. $FmtV['$LinkUpload'] =
  153. FmtPageName("\$PageUrl?action=upload&amp;upname=$encname", $pagename);
  154. $FmtV['$LinkText'] = $txt;
  155. if (!file_exists($filepath))
  156. return FmtPageName($LinkUploadCreateFmt, $pagename);
  157. $path = PUE(FmtPageName(IsEnabled($EnableDirectDownload, 1)
  158. ? "$UploadUrlFmt$UploadPrefixFmt/$encname"
  159. : "{\$PageUrl}?action=download&amp;upname=$encname",
  160. $pagename));
  161. return LinkIMap($pagename, $imap, $path, $alt, $txt, $fmt);
  162. }
  163. # Authenticate group downloads with the group password
  164. function UploadAuth($pagename, $auth, $cache=0){
  165. global $GroupAttributesFmt, $EnableUploadGroupAuth;
  166. if (IsEnabled($EnableUploadGroupAuth,0)){
  167. SDV($GroupAttributesFmt,'$Group/GroupAttributes');
  168. $pn_upload = FmtPageName($GroupAttributesFmt, $pagename);
  169. } else $pn_upload = $pagename;
  170. $page = RetrieveAuthPage($pn_upload, $auth, true, READPAGE_CURRENT);
  171. if (!$page) Abort("?No '$auth' permissions for $pagename");
  172. if ($cache) PCache($pn_upload,$page);
  173. return true;
  174. }
  175. function UploadSetVars($pagename) {
  176. global $Author, $FmtV, $UploadExtMax, $EnableReadOnly,
  177. $EnablePostAuthorRequired, $EnableUploadAuthorRequired;
  178. $FmtV['$UploadName'] = MakeUploadName($pagename,@$_REQUEST['upname']);
  179. $FmtV['$UploadAuthor'] = PHSC($Author, ENT_QUOTES);
  180. $upresult = PHSC(@$_REQUEST['upresult']);
  181. $uprname = PHSC(@$_REQUEST['uprname']);
  182. $FmtV['$upext'] = PHSC(@$_REQUEST['upext']);
  183. $FmtV['$upmax'] = PHSC(@$_REQUEST['upmax']);
  184. $FmtV['$UploadResult'] = ($upresult) ?
  185. FmtPageName("<i>$uprname</i>: $[UL$upresult]",$pagename) :
  186. (@$EnableReadOnly ? XL('Cannot modify site -- $EnableReadOnly is set'): '');
  187. $FmtV['$UploadAuthorRequired'] = @$EnableUploadAuthorRequired ?
  188. 'required="required"' : '';
  189. }
  190. function HandleUpload($pagename, $auth = 'upload') {
  191. global $HandleUploadFmt,$PageStartFmt,$PageEndFmt,$PageUploadFmt;
  192. UploadAuth($pagename, $auth, 1);
  193. UploadSetVars($pagename);
  194. SDV($HandleUploadFmt,array(&$PageStartFmt,&$PageUploadFmt,&$PageEndFmt));
  195. PrintFmt($pagename,$HandleUploadFmt);
  196. }
  197. function HandleDownload($pagename, $auth = 'read') {
  198. global $UploadFileFmt, $UploadExts, $DownloadDisposition, $EnableIMSCaching;
  199. SDV($DownloadDisposition, "inline");
  200. UploadAuth($pagename, $auth);
  201. $upname = MakeUploadName($pagename, @$_REQUEST['upname']);
  202. $filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);
  203. if (!$upname || !file_exists($filepath)) {
  204. header("HTTP/1.0 404 Not Found");
  205. Abort("?requested file not found");
  206. exit();
  207. }
  208. if (IsEnabled($EnableIMSCaching, 0)) {
  209. header('Cache-Control: private');
  210. header('Expires: ');
  211. $filelastmod = gmdate('D, d M Y H:i:s \G\M\T', filemtime($filepath));
  212. if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] == $filelastmod)
  213. { header("HTTP/1.0 304 Not Modified"); exit(); }
  214. header("Last-Modified: $filelastmod");
  215. }
  216. preg_match('/\\.([^.]+)$/',$filepath,$match);
  217. if ($UploadExts[@$match[1]])
  218. header("Content-Type: {$UploadExts[@$match[1]]}");
  219. $fsize = $length = filesize($filepath);
  220. $end = $fsize-1;
  221. header("Accept-Ranges: bytes");
  222. if (@$_SERVER['HTTP_RANGE']) {
  223. if(! preg_match('/^\\s*bytes\\s*=\\s*(\\d*)\\s*-\\s*(\\d*)\\s*$/i', $_SERVER['HTTP_RANGE'], $r)
  224. || intval($r[1])>$end
  225. || intval($r[2])>$end
  226. || ($r[2] && intval($r[1])>intval($r[2]))
  227. ) {
  228. header('HTTP/1.1 416 Requested Range Not Satisfiable');
  229. header("Content-Range: bytes 0-$end/$fsize");
  230. exit;
  231. }
  232. if ($r[2]=='') $r[2] = $end;
  233. if ($r[1]=='') $r[1] = $end - $r[2];
  234. $length = $r[2] - $r[1] + 1;
  235. header('HTTP/1.1 206 Partial Content');
  236. header("Content-Range: bytes $r[1]-$r[2]/$fsize");
  237. }
  238. else {
  239. $r = array( null, 0, $end);
  240. }
  241. header("Content-Length: $length");
  242. header("Content-Disposition: $DownloadDisposition; filename=\"$upname\"");
  243. $fp = fopen($filepath, "rb");
  244. if ($fp) {
  245. $bf = 8192;
  246. fseek($fp, $r[1]);
  247. while (!feof($fp) && ($pos = ftell($fp)) <= $r[2]) {
  248. $bf = max($bf, $r[2] - $pos + 1);
  249. echo fread($fp, $bf);
  250. flush();
  251. }
  252. fclose($fp);
  253. }
  254. exit();
  255. }
  256. function HandlePostUpload($pagename, $auth = 'upload') {
  257. global $UploadVerifyFunction, $UploadFileFmt, $LastModFile,
  258. $EnableUploadVersions, $Now, $RecentUploadsFmt, $FmtV,
  259. $NotifyItemUploadFmt, $NotifyItemFmt, $IsUploadPosted,
  260. $UploadRedirectFunction, $UploadPermAdd, $UploadPermSet,
  261. $EnableReadOnly;
  262. if (IsEnabled($EnableReadOnly, 0))
  263. Abort('Cannot modify site -- $EnableReadOnly is set', 'readonly');
  264. UploadAuth($pagename, $auth);
  265. $uploadfile = $_FILES['uploadfile'];
  266. $upname = @$_REQUEST['upname'];
  267. if ($upname=='') $upname=$uploadfile['name'];
  268. $upname = MakeUploadName($pagename,$upname);
  269. if (!function_exists($UploadVerifyFunction))
  270. Abort('?no UploadVerifyFunction available');
  271. $filepath = FmtPageName("$UploadFileFmt/$upname",$pagename);
  272. $result = $UploadVerifyFunction($pagename,$uploadfile,$filepath);
  273. if ($result=='') {
  274. $filedir = preg_replace('#/[^/]*$#','',$filepath);
  275. mkdirp($filedir);
  276. if (IsEnabled($EnableUploadVersions, 0))
  277. @rename($filepath, "$filepath,$Now");
  278. if (!move_uploaded_file($uploadfile['tmp_name'],$filepath))
  279. { Abort("?cannot move uploaded file to $filepath"); return; }
  280. fixperms($filepath, $UploadPermAdd, $UploadPermSet);
  281. if ($LastModFile) { touch($LastModFile); fixperms($LastModFile); }
  282. $result = "upresult=success";
  283. $FmtV['$upname'] = $upname;
  284. $FmtV['$upsize'] = $uploadfile['size'];
  285. if (IsEnabled($RecentUploadsFmt, 0)) {
  286. PostRecentChanges($pagename, '', '', $RecentUploadsFmt);
  287. }
  288. if (IsEnabled($NotifyItemUploadFmt, 0) && function_exists('NotifyUpdate')) {
  289. $NotifyItemFmt = $NotifyItemUploadFmt;
  290. $IsUploadPosted = 1;
  291. register_shutdown_function('NotifyUpdate', $pagename, getcwd());
  292. }
  293. }
  294. $FmtV['$upresult'] = $result;
  295. SDV($UploadRedirectFunction, 'Redirect');
  296. $UploadRedirectFunction($pagename,"{\$PageUrl}?action=upload&uprname=$upname&$result");
  297. }
  298. function UploadVerifyBasic($pagename,$uploadfile,$filepath) {
  299. global $EnableUploadOverwrite,$UploadExtSize,$UploadPrefixQuota,
  300. $UploadDirQuota,$UploadDir, $UploadBlacklist,
  301. $Author, $EnablePostAuthorRequired, $EnableUploadAuthorRequired;
  302. if (IsEnabled($EnableUploadAuthorRequired,0) && !$Author)
  303. return 'upresult=authorrequired';
  304. if (count($UploadBlacklist)) {
  305. $tmp = explode("/", $filepath);
  306. $upname = strtolower(end($tmp));
  307. foreach($UploadBlacklist as $needle) {
  308. if (strpos($upname, $needle)!==false) return 'upresult=badname';
  309. }
  310. }
  311. if (!$EnableUploadOverwrite && file_exists($filepath))
  312. return 'upresult=exists';
  313. preg_match('/\\.([^.\\/]+)$/',$filepath,$match); $ext=@$match[1];
  314. $maxsize = $UploadExtSize[$ext];
  315. if ($maxsize<=0) return "upresult=badtype&upext=$ext";
  316. if ($uploadfile['size']>$maxsize)
  317. return "upresult=toobigext&upext=$ext&upmax=$maxsize";
  318. switch (@$uploadfile['error']) {
  319. case 1: return 'upresult=toobig';
  320. case 2: return 'upresult=toobig';
  321. case 3: return 'upresult=partial';
  322. case 4: return 'upresult=nofile';
  323. }
  324. if (!is_uploaded_file($uploadfile['tmp_name'])) return 'upresult=nofile';
  325. $filedir = preg_replace('#/[^/]*$#','',$filepath);
  326. if ($UploadPrefixQuota &&
  327. (dirsize($filedir)-@filesize($filepath)+$uploadfile['size']) >
  328. $UploadPrefixQuota) return 'upresult=pquota';
  329. if ($UploadDirQuota &&
  330. (dirsize($UploadDir)-@filesize($filepath)+$uploadfile['size']) >
  331. $UploadDirQuota) return 'upresult=tquota';
  332. return '';
  333. }
  334. function dirsize($dir) {
  335. $size = 0;
  336. $dirp = @opendir($dir);
  337. if (!$dirp) return 0;
  338. while (($file=readdir($dirp)) !== false) {
  339. if ($file[0]=='.') continue;
  340. if (is_dir("$dir/$file")) $size+=dirsize("$dir/$file");
  341. else $size+=filesize("$dir/$file");
  342. }
  343. closedir($dirp);
  344. return $size;
  345. }
  346. function FmtUploadList($pagename, $args) {
  347. global $UploadDir, $UploadPrefixFmt, $UploadUrlFmt, $EnableUploadOverwrite,
  348. $TimeFmt, $EnableDirectDownload, $IMapLinkFmt, $UrlLinkFmt, $FmtV;
  349. $opt = ParseArgs($args);
  350. if (@$opt[''][0]) $pagename = MakePageName($pagename, $opt[''][0]);
  351. $matchfnames = '';
  352. if (@$opt['names'] ) $matchfnames = $opt['names'];
  353. if (@$opt['ext'])
  354. $matchfnames .= FixGlob($opt['ext'], '$1*.$2');
  355. $uploaddir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
  356. $uploadurl = FmtPageName(IsEnabled($EnableDirectDownload, 1)
  357. ? "$UploadUrlFmt$UploadPrefixFmt/"
  358. : "\$PageUrl?action=download&amp;upname=",
  359. $pagename);
  360. $dirp = @opendir($uploaddir);
  361. if (!$dirp) return '';
  362. $filelist = array();
  363. while (($file=readdir($dirp)) !== false) {
  364. if ($file[0] == '.') continue;
  365. if ($matchfnames && ! MatchNames($file, $matchfnames)) continue;
  366. $filelist[$file] = rawurlencode($file);
  367. }
  368. closedir($dirp);
  369. $out = array();
  370. natcasesort($filelist);
  371. $overwrite = '';
  372. $fmt = IsEnabled($IMapLinkFmt['Attach:'], $UrlLinkFmt);
  373. foreach($filelist as $file=>$encfile) {
  374. $FmtV['$LinkUrl'] = PUE("$uploadurl$encfile");
  375. $FmtV['$LinkText'] = $file;
  376. $FmtV['$LinkUpload'] =
  377. FmtPageName("\$PageUrl?action=upload&amp;upname=$encfile", $pagename);
  378. $stat = stat("$uploaddir/$file");
  379. if ($EnableUploadOverwrite)
  380. $overwrite = FmtPageName("<a rel='nofollow' class='createlink'
  381. href='\$LinkUpload'>&nbsp;&Delta;</a>",
  382. $pagename);
  383. $lnk = FmtPageName($fmt, $pagename);
  384. $out[] = "<li> $lnk$overwrite ... ".
  385. number_format($stat['size']) . " bytes ... " .
  386. strftime($TimeFmt, $stat['mtime']) . "</li>";
  387. }
  388. return implode("\n",$out);
  389. }
  390. # this adds (:if [!]attachments filepattern pagename:) to the markup
  391. $Conditions['attachments'] = "AttachExist(\$pagename, \$condparm)";
  392. function AttachExist($pagename, $condparm='*') {
  393. global $UploadFileFmt;
  394. @list($fpat, $pn) = explode(' ', $condparm, 2);
  395. $pn = ($pn > '') ? MakePageName($pagename, $pn) : $pagename;
  396. $uploaddir = FmtPageName($UploadFileFmt, $pn);
  397. $flist = array();
  398. $dirp = @opendir($uploaddir);
  399. if ($dirp) {
  400. while (($file = readdir($dirp)) !== false)
  401. if ($file[0] != '.') $flist[] = $file;
  402. closedir($dirp);
  403. $flist = MatchNames($flist, $fpat);
  404. }
  405. return count($flist);
  406. }