/-pattern that allows spaces in the filename SDV($UploadExtNamePattern,"(?:(\\/*$UploadDirPattern*)$UploadExtCharPattern+)"); SDV($UploadVerifyFunction,"UploadVerifyBasic"); SDV($PageUploadFmt, "

$[Attachments for] \$PageName

\$UploadResult

$[File to upload:]
$[Name attachment as:]
"); SDV($HandleUploadFmt,array(&$PageStartFmt, &$PageUploadFmt, "wiki:$[PmWiki.UploadQuickReference]", &$PageEndFmt)); SDV($UploadFileFmt,"$UploadDir$UploadPrefixFmt"); SDV($RecentUploads, array( 'Main.AllRecentUploads' => "[[$UploadUrlFmt$UploadPrefixFmt\$UploadName \$UploadName]]", '$Group.RecentUploads' => '[[Attach:$UploadName $UploadName]]')); XLSDV('en',array( 'ULsuccess' => 'successfully uploaded', 'ULbadname' => 'invalid attachment name', 'ULbadtype' => '\'$upext\' is not an allowed file extension', 'ULtoobig' => 'file is larger than maximum allowed by webserver', 'ULtoobigext' => 'file is larger than allowed maximum of $upextmax bytes for \'$upext\' files', 'ULpartial' => 'incomplete file received', 'ULnofile' => 'no file uploaded', 'ULexists' => 'file with that name already exists', 'ULpquota' => 'group quota exceeded', 'ULtquota' => 'upload quota exceeded')); SDV($PageAttributes['passwdupload'],'$[Set new upload password]: '); SDV($DefaultPasswords['upload'],'*'); SDV($LinkPatterns[120]["\\bAttach:($UploadNamePattern)"],'FmtAttachLink'); SDV($InterMapUrls['Attach'], FmtPageName("$UploadUrlFmt$1",$pagename)); // Old value for the InterMap was: // FmtPageName("$UploadUrlFmt$UploadPrefixFmt$1",$pagename)); // but the '$UploadPrefixFmt' must go to allow "absolute" paths SDV($InlineReplacements['/\\[\\[\\$Attachlist(?:\\s+(.*))?\\]\\]/e'], "FmtUploadList('$pagename','$1')"); SDV($DoubleBrackets["/\\[\\[\\$?Attachlist:((?:\\/|$UploadCharPattern)*)" .'(?:\\s+([^\\s]+))?\\]\\]/e'], "FmtUploadListPath('$pagename','$1','$2')"); // New syntax: [[attachlist:]] SDV($DoubleBrackets["/\\[\\[attachlist:((?:\\/|$UploadCharPattern)*)" .'(?:\\s+([^\\s]+))?\\]\\]/e'], "FmtUploadListPath('$pagename','$1','$2')"); // New syntax: [[attach:]] /* SDV($DoubleBrackets["/\\[\\[attach:($UploadExtNamePattern)\\]\\]/"], 'FmtAttachStatement'); */ SDV($LinkPatterns[120]["\\[\\[attach:($UploadExtNamePattern)\\]\\]"], 'FmtAttachStatement'); $UploadName = $upname; $UploadResult=''; if ($upresult) $UploadResult = "$upname: ".FmtPageName("$[UL$upresult]",$pagename); if ($upresult=='success') $UploadName = ""; mkgiddir($UploadDir); SDV($WikiLibDirs,array($WikiDir,"wikilib.d")); SDV($HandleActions['upload'],'HandleUpload'); SDV($HandleActions['postupload'],'HandlePostUpload'); SDV($HandleActions['dir'], 'HandleDir'); /** function: restoreSlashes // Because of weird behaviour in Internet Explorer, this function can // be used instead of rawurlencode(), where '/' will *not* be replaced // with '%2F', so that paths' work in IE as well. */ if(!function_exists('uriEncodeWoSlash')){ function uriEncodeWoSlash($text) { return preg_replace("/%2F/i", "/", rawurlencode($text)); } } function FmtAttachLink($pat,$ref,$txt) { global $UploadName,$UploadFileFmt,$pagename,$UploadFormTarget,$FmtUrlLink, $ImgExtPattern; preg_match("/^([^:]*):(.*)$/",$ref,$match); $UploadName = $match[2]; // Extract path component $path = UploadPathAdjust($match[2], $pagename, 'file'); // Adjust path if(!$path['legal']) return Keep("Illegal path in ".$ref.""); if(is_dir($path['full'])) return Keep("Error:Path refers to a directory in " ."'".$ref."'"); if (!file_exists($path['full'])) { $target = ($UploadFormTarget) ? "target='$UploadFormTarget'" : ''; return (is_null($txt) ? $ref : $txt) . "?"; } if(preg_match("/$ImgExtPattern\$/", '.'.$path['ext']) && is_null($txt)){ $ref = Keep(uriEncodeWoSlash(substr($path['path'], 0, -(1+strlen($path['ext']))))) .'.'.$path['ext']; $rtxt = null; // Otherwise the image won't be shown } else { $rtxt = is_null($txt) ? $ref : $txt; $ref = Keep(uriEncodeWoSlash($path['path'])); } return $FmtUrlLink($pat,"Attach:/" . $ref, $rtxt); } function FmtAttachStatement($pat,$ref,$txt) { global $UploadName,$UploadFileFmt,$pagename,$UploadFormTarget,$FmtUrlLink, $ImgExtPattern; preg_match("/^([^:]*):(.*)\\]\\]$/",$ref,$match); $UploadName = $match[2]; // Extract path component $path = UploadPathAdjust($match[2], $pagename, 'file'); // Adjust path if(!$path['legal']) return Keep("Illegal path in ".$ref.""); if(is_dir($path['full'])) return Keep("Error:Path refers to a directory in " ."'".$ref."'"); if (!file_exists($path['full'])) { $target = ($UploadFormTarget) ? "target='$UploadFormTarget'" : ''; return (is_null($txt) ? $ref : $txt) . "?"; } if(preg_match("/$ImgExtPattern\$/", '.'.$path['ext']) && is_null($txt)){ $ref = Keep(uriEncodeWoSlash(substr($path['path'], 0, -(1+strlen($path['ext']))))) .'.'.$path['ext']; $rtxt = null; // Otherwise the image won't be shown } else { $rtxt = is_null($txt) ? substr($ref, 9, -2) : $txt; $ref = Keep(uriEncodeWoSlash($path['path'])); } Verbose(2, sprintf("rtxt='%s', path='%s'\n", $rtxt, $path['path'])); return $FmtUrlLink("Attach:(.*)","Attach:/" . $ref, $rtxt); } function HandleUpload($pagename) { global $HandleUploadFmt; $page = RetrieveAuthPage($pagename,'upload'); if (!$page) { Abort("?cannot upload to $pagename"); } PrintFmt($pagename,$HandleUploadFmt); } function HandlePostUpload($pagename) { global $HTTP_POST_FILES,$UploadName,$UploadFileFmt, $EnablePathInfo, $UploadVerifyFunction,$UploadPerms,$RecentUploads,$TimeFmt,$Now; $page = RetrieveAuthPage($pagename,'upload'); if (!$page) Abort("?cannot upload to $pagename"); $uploadfile = $HTTP_POST_FILES['uploadfile']; if ($UploadName=='') { $UploadName=$uploadfile['name']; } if (!function_exists($UploadVerifyFunction)) Abort("?no UploadVerifyFunction available"); $path = UploadPathAdjust($UploadName, $pagename, 'file'); $result = $UploadVerifyFunction($pagename,$uploadfile,$path['full']); if(!$path['legal']) $result='upresult=badname'; elseif ($result=='') { mkdirRecursive(dirname($path['full'])); if (!move_uploaded_file($uploadfile['tmp_name'],$path['full'])) { Abort("?cannot move uploaded file to ".$path['full']); return; } chmod($path['full'], $UploadPerms); foreach($RecentUploads as $rcfmt => $pgfmt) { $rcname=FmtPageName($rcfmt,$pagename); if (!$rcname) continue; $pgname=FmtPageName($pgfmt,$pagename); if (!$pgname) continue; if (@$seen[$rcname]++) continue; $rcpage = ReadPage($rcname,""); $rcpage['text'] = "* $pgname . . . . . . ".strftime($TimeFmt,$Now)."\n". preg_replace("%\\* ".preg_quote($pgname)." .*?\n%","", $rcpage['text']); WritePage($rcname,$rcpage); } $result = "upresult=success"; } $glueChar = isset($EnablePathInfo) && !$EnablePathInfo ? '&' : '?'; Redirect($pagename, '$PageUrl'.$glueChar.'action=upload&upname=' .rawurlencode($UploadName)."&$result"); } function dirsize($dir) { $size=0; $dirp = @opendir($dir); if (!$dirp) return 0; while (($file=readdir($dirp)) !== false) { if ($file[0]=='.') continue; if (is_dir("$dir/$file")) $size+=dirsize("$dir/$file"); else $size+=filesize("$dir/$file"); } closedir($dirp); return $size; } function UploadVerifyBasic($pagename,$uploadfile,$filepath) { global $UploadName,$UploadExtSize,$EnableUploadOverwrite, $UploadPrefixQuota,$UploadDirQuota,$UploadDir; if (!$EnableUploadOverwrite && file_exists($filepath)) return 'upresult=exists'; preg_match('/\\.([^.]+)$/',$filepath,$match); $ext=@$match[1]; $maxsize = $UploadExtSize[$ext]; if ($maxsize<=0) return "upresult=badtype&upext=$ext"; if ($uploadfile['size']>$maxsize) return "upresult=toobigext&upext=$ext"; if (!is_uploaded_file($uploadfile['tmp_name'])) return 'upresult=nofile'; switch ($uploadfile['error']) { case 1: return 'upresult=toobig'; case 2: return 'upresult=toobig'; case 3: return 'upresult=partial'; case 4: return 'upresult=nofile'; } $dir = dirname($filepath); if ($UploadPrefixQuota && (@(dirsize($dir)-filesize($filepath)+$uploadfile['size']) > $UploadPrefixQuota)) return 'upresult=pquota'; if ($UploadDirQuota && @(dirsize($UploadDir)-filesize($filepath)+$uploadfile['size']) > $UploadDirQuota) return 'upresult=tquota'; return ''; } /** Function: HandleDir Returns Parameters: action=dir path= */ function HandleDir($pagename) { global $HTTP_POST_VARS, $HTTP_GET_VARS; $page = RetrieveAuthPage($pagename, 'upload'); if(!$page) Abort("?cannot list uploaded files of $pagename"); header("Content-Type: text/plain"); $pathArg=$HTTP_POST_VARS['dir']; if($HTTP_GET_VARS['path']) $pathArg=$HTTP_GET_VARS['path']; $path=UploadPathAdjust($pathArg, $pagename); if (!$path['legal']) Abort("?Illegal path: ".$path['path']); echo FmtUploadDir($path['full'], '', 'N=A', false); } function FmtUploadList($pagename,$order='N=A') { global $UploadDir,$UploadPrefixFmt,$UploadUrlFmt,$TimeFmt; $dir = FmtPageName("$UploadDir$UploadPrefixFmt",$pagename); $url = FmtPageName("$UploadUrlFmt$UploadPrefixFmt",$pagename); if ($order=='') $order='N=A'; // The calls to substr() below are used to remove the trailing '/' return "\n\n"; } // Help function that checks path for illegal elements, e.g. '/../' function IsUploadPathLegal($path) { return strpos($path,"/../") === false;} /** Function: UploadPathAdjust // Adjust '$path' as follows. // * If $path is empty and $type='file', then return an empty structure. // * Default value for path is '$Group'. // * A relative path gets '$Group/' prepended to it // Finally, any trailing '/' are removed (just to be tidy) // // The output is an array with the following elements: // boolean 'legal' // string 'path' - resolved path (relative to upload directory) // string 'base' - same as 'path' but without any extension // string 'ext' - any extension in 'path' // string 'full' - full path (to directory or file) // string 'URI' - full URI (to directory or file) // Example: 'dir1/aFile.txt' when in the group 'Group' produces: // 'legal' => true // 'path' => 'Group/dir1/aFile.txt' // 'base' => 'Group/dir1/aFile' // 'ext' => 'txt' // 'full' => 'uploads/Group/dir1/aFile.txt' // 'URI' => 'http://.../uploads/Group/dir1/aFile.txt' */ function UploadPathAdjust($path, $pagename, $type='dir') { global $UploadDir, $UploadUrlFmt, $UploadPrefixFmt; if('file'==$type && ''==$path) return array('legal' => false, 'path' => '', 'full' => '', 'URI' => ''); $legal = IsUploadPathLegal($path); if(''==$path) // Is path empty? $path=FmtPageName($UploadPrefixFmt, $pagename); elseif('/' !== $path[0]) // Is path relative? $path=FmtPageName($UploadPrefixFmt, $pagename)."$path"; // Just to be tidy, remove inital '/' and any trailing '/' $path = '/' == substr($path, -1) ? substr($path, 1, -1) : substr($path, 1); if('file'==$type && '' == $path) Abort("?The variable '\$path' is empty"); $file_parts = pathinfo('dummy/' . $path); $file_extension = $file_parts['extension']; return '' == $path ? array('legal' => $legal, 'path' => $path, 'ext' => '', 'full' => FmtPageName("$UploadDir", $pagename), 'URI' => FmtPageName("$UploadUrlFmt", $pagename)) : array('legal' => $legal, 'path' => $path, 'ext' => $file_extension, 'full' => FmtPageName("$UploadDir/", $pagename).$path, 'URI' => FmtPageName("$UploadUrlFmt/", $pagename).$path); } function FmtUploadListPath($pagename,$dir,$order='N=A') { if ($order=='') $order='N=A'; Verbose(3, "[[\$Attachlist:%s]]", $dir); $path = UploadPathAdjust($dir, $pagename); Verbose(4, "modified path = %s", $path['path']); if(!$path['legal']) return "Attachlist: Illegal path. ". "The path may not contain /../ !
"; if(!is_dir($path['full'])) return "Attachlist: Directory '".$path['dir']."' does not exist!
"; // return Keep($dir); return Keep("\n\n"); } // Question: Should the function below really be called 'Fmt...'? function FmtUploadDir($dir,$url,$o,$html=true) { global $TimeFmt, $UploadDir; $dirp = @opendir($dir); $out = ''; if (!$dirp) return $out; $filelist = array(); while (($file=readdir($dirp)) !== false) { if ($file[0]=='.') continue; switch (strtolower($o[0])) { case 'm': $filelist[$file]=filemtime("$dir/$file"); break; case 's': $filelist[$file]=filesize("$dir/$file"); break; default: $filelist[$file]=$file; break; } } closedir($dirp); if (strtolower($o[2])=='d') arsort($filelist); else asort($filelist); $fmtDir = $html ? "\n\t
  • %s/ . . . . . . . %s\n
  • " : "%-40s/ . . . . . . %s\n%s"; $l = strlen($UploadDir); foreach($filelist as $file=>$x) { $stat = stat("$dir/$file"); if(is_dir("$dir/$file")) { $out .= $html ? sprintf($fmtDir, $file, strftime($TimeFmt,$stat['mtime']), FmtUploadDir("$dir/$file", "$url/".uriEncodeWoSlash($file), $o, $html)) : FmtUploadDir("$dir/$file", "$url/".uriEncodeWoSlash($file), $o, $html); } else { $out .= $html ? sprintf("\n\t
  • %s ... %d bytes %s
  • ", $url, uriEncodeWoSlash($file), $file, $stat['size'], strftime($TimeFmt,$stat['mtime'])) : sprintf("%-30s %6d bytes %s\n", substr($dir,$l)."/".$file, $stat['size'], strftime($TimeFmt,$stat['mtime'])); } } return $out; } function mkdirRecursive($dir){ $parent=dirname($dir); if(is_dir($parent)) return mkgiddir($dir); mkdirRecursive($parent); if(!is_dir($parent)) Abort("Failed to make parent directory $parent"); mkgiddir($dir); } ?>