PmWiki/mini/mini.php
<?php if(!defined('PmWiki'))exit;
/**
A mini square thumbnail generator for PmWiki
Written by (c) Petko Yotov 2006-2011
This text is written for PmWiki; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See pmwiki.php for full details
and lack of warranty.
This text is partly based on the ThumbList2 picture gallery
and on the PmWiki upload.php script.
Copyright 2006-2011 Petko Yotov http://notamment.fr
Copyright 2004-2007 Patrick R. Michaud http://www.pmichaud.com
*/
$RecipeInfo['Mini']['Version'] = '20110828';
# patch Walter: on the server (if $MiniGeneratedAlready=TRUE) do not check that the thumbnails are younger than the originals,
# the timestamp is set by the copy to the server
# and the thumbnails should be correctly generated locally before copy to the server!
SDV($MiniGeneratedAlready, FALSE);
SDVA($Mini, array('EnableLightbox' => 0,
'ImgFmt' => '<img class="mini" src="%1$s" title="%2$s" alt="%2$s" border="0" />',
'LinkFmt' => '<a href="%2$s" class="minilink" %3$s>%1$s</a>',
'MiniFmt' => '%s',
'ImTypes' => array(1=>"gif",2=>"jpeg",3=>"png",15=>"wbmp",16=>"xbm"),
'ImRx' => array("/\\.(gif|png|jpe|jpe?g|wbmp|xbm)$/i", "!^th\\d+---!"),
'LbUrl' => '$FarmPubDirUrl/ultralightbox',
'LbFiles' => array('unverse.js', 'ultralightbox.js', 'ultralightbox.css'),
'LbRels' => array('','%s_mini','%s_mini_%d','%s'),
'EnableCache' => 0, 'CacheFilename' => '.%s.mini-cache.txt',
'FixFilenames' => 0,
'CreateFunction' => 'MiniCreate',
'PurgeRedirectFmt' => '{$PageUrl}?action=upload',
'GalPattern' => "(?:{$GroupPattern}\\.?\\/|{$NamePattern}\\/|{$GroupPattern}[.\\/]{$NamePattern}\\/)?$KeepToken\\d+$KeepToken|",
));
SDVA($Mini['thumbs'], array('x'=>'100x100x50x50x90xffffff'));
SDVA($Mini['FixFilenamePatterns'], array('/\\s/'=>'_', '/[^-\\w.]/'=>''));
SDVA($Mini['FNameRPat'], array("/\\.\\w{3,4}$/i"=>'', '/_+/'=>' '));
SDVA($HandleActions, array('mini'=>'HandleMini','purgethumbs'=>'HandlePurgeMini'));
Markup('Mini:','<links',
"/\\b([Mm]ini\\d?(?:_\\w+)?:)({$Mini['GalPattern']}[^\\s\"\\|\\[\\]$KeepToken%]+)(\"([^\"]*)\")?/e",
"Keep(LinkMini(\$pagename,'$1','$2','$4','$1$2'),'L')");
Markup('(:mini:)', 'directives', '/\\(:mini (.+):\\)/e', "MiniConf(PSS('$1'))");
function LinkMini($PN, $imap, $path, $alt, $txt, $fmt=NULL, $listonly=0){
global $FmtV, $UploadFileFmt, $LinkUploadCreateFmt, $UploadUrlFmt, $PCache, $KeepToken, $KPV,
$UploadPrefixFmt, $EnableDirectDownload, $Mini, $MiniGeneratedAlready;
if(! function_exists('imagecreate'))
return "Mini: PHP-GD image library not found. Exiting.";
static $cnt = 0; $cnt++;
$lb = sprintf(@$Mini['LbRels'][ $Mini['EnableLightbox'] ], 'lightbox', $cnt);
if($Mini['EnableLightbox'] && ! $listonly) MiniHeaderFmt();
$ptime = $PCache[$PN]['time'];
$test_cache = ($Mini['EnableCache'] && !@$_POST['preview'] && !$listonly);
if($test_cache){
$cachedir = FmtPageName($UploadFileFmt, $PN);
$cachefile = sprintf("$cachedir/{$Mini['CacheFilename']}", $PN);
if(!@$_GET['recache'] && !(isset($Mini['Cache'][0]) && isset($Mini['Cache'][$cnt]))){
$Mini['Cache'][0] = 1;
if(file_exists($cachefile) && filemtime($cachefile) >= $ptime){
$cache = implode('', file($cachefile));
preg_match_all("/<(Mini(\\d+))>(.*?)<\\/\\1>/", $cache, $m);
foreach($m[2] as $i=>$x)$Mini['Cache'][$x] = $m[3][$i];
}
}
if(isset($Mini['Cache'][$cnt])) return $Mini['Cache'][$cnt];
}
$cache_ok = 1;
$opage="";
if (preg_match('!^(.*)/([^/]+)$!', $path, $m)) {
$path = $m[2]; $PN = MakePageName($PN, $m[1]);
$opage=$m[1]."/";
}
$uploadurl = FmtPageName(IsEnabled($EnableDirectDownload,1)
? "$UploadUrlFmt$UploadPrefixFmt/"
: "\$PageUrl?action=download&upname=",
$PN);
$flist = $tlist = array(); $prelistwrap=$prelist=$path;
if(strpos($path, $KeepToken) !== false) {
$prelist = MarkupRestore($path);
if(preg_match_all('/^\\s*([^\\s"\\|\\[\\]%]+)(?:"(.*)")?\\s*$/m', $prelist, $match, PREG_SET_ORDER)) {
$path = '';
foreach($match as $k=>$a) {
if($path) $path .= ',';
$path .= $a[1];
$tlist[$a[1]] = $a[2];
}
}
$prelistwrap = "[=$prelist=]";
}
$Mini['SourceMarkup'][$cnt] = "$imap$opage$prelistwrap"; if($alt) $Mini['SourceMarkup'][$cnt] .= "\"$alt\"";
$Mini['SourcePrefix'][$cnt] = "$imap$opage";
if(preg_match("/(^|,)[!-]|[\\*\\?]/", $path)){
$uploaddir = FmtPageName($UploadFileFmt, $PN);
if($dirp=@opendir($uploaddir)){
while (($f=readdir($dirp))!==false)if($f{0}!='.')$flist[$f]=$f;
closedir($dirp);
}
$flist = MatchNames($flist, array_merge($Mini['ImRx'], array($path)));
natcasesort($flist);
}
foreach(explode(',', $path) as $v)$mylist[$v] = $v;
$mylist = array_merge(preg_grep("/^[!-]|[\\*\\?]/", $mylist, PREG_GREP_INVERT), $flist);
if(preg_match("/^(Mini)(\\d)(_\\w+)?:$/i", $imap, $m) ){
$imap = "{$m[1]}{$m[3]}:"; $pxidx = intval($m[2]);
}
else $pxidx = 0;
if(preg_match("/^Mini_(\\w+):$/i", $imap, $m) ){
$imap = substr($imap, 0, 4).':'; $uMini = "uMini_{$m[1]}";
if(function_exists($uMini) ) $mylist = $uMini($mylist); else return "$txt$alt";
}
$ImgFmt = IsEnabled($Mini["ImgFmt$pxidx"], $Mini['ImgFmt']);
$LinkFmt = IsEnabled($Mini["LinkFmt$pxidx"], $Mini['LinkFmt']);
$MiniFmt = IsEnabled($Mini["MiniFmt$pxidx"], $Mini['MiniFmt']);
$html = array();
$htmlH = $htmlF = '';
foreach($mylist as $file=>$v){
list($upname, $fpath) = MiniFixFName($PN, $v);
$picurl = PUE("$uploadurl$upname");
if($listonly){ $html[] = "\n$upname"; continue; }
if(!file_exists($fpath)){
if(@$Mini['nofileurl']) {
$html[] = sprintf($ImgFmt, $Mini['nofileurl'], '');
}
else {
$FmtV['$LinkText'] = $upname;
$FmtV['$LinkUpload'] =
FmtPageName("\$PageUrl?action=upload&upname=$upname", $PN);
$html[] = FmtPageName($LinkUploadCreateFmt, $PN);
}
continue;
}
list($w, $h, $t) = @getimagesize($fpath, $info);
if(!isset($Mini['ImTypes'][$t])){
$html[] = LinkIMap($PN, "Attach:", $upname, $alt, "Attach:$upname", $fmt);
continue;
}
$mupname = "th0$pxidx---$upname.jpg";
$mpath = FmtPageName("$UploadFileFmt/$mupname", $PN);
if(file_exists($mpath) && ($MiniGeneratedAlready || filemtime($mpath)>=filemtime($fpath))) {
$miniurl = PUE("$uploadurl$mupname");
}else{
$miniurl = PUE(FmtPageName("{\$PageUrl}?action=mini&idx=$pxidx&upname=$upname", $PN));
$cache_ok = 0; NoCache();
}
if(@$tlist[$v]>'') $xalt=str_replace('"', """, strip_tags($tlist[$v]));
elseif(trim($alt) == '-') $xalt='';
elseif($alt>'') $xalt=str_replace('"', """, strip_tags($alt));
else $xalt = preg_replace(array_keys($Mini['FNameRPat']), array_values($Mini['FNameRPat']), $v);
if(IsEnabled($Mini['EnableHeaderFooter'], 0) && strpos($xalt, '|')!==false){
list($htmlH, $htmlF) = explode('|', $xalt, 2);
$xalt = trim("$htmlH $htmlF");
}
$out = sprintf($ImgFmt, $miniurl, $xalt, $picurl, $upname, $cnt);
if($imap == 'Mini:'){ # links enabled
$rel='';
if($Mini['EnableLightbox']){
$rel = "rel='$lb' title=\"$xalt\"";
}
$out = sprintf($LinkFmt, $out, $picurl, $rel, $miniurl, $xalt, $lb, $cnt);
}
$html[] = $out;
}
$html = sprintf($MiniFmt, implode(' ', $html), $cnt);
if($htmlH) $html = "<span class='miniH'>$htmlH</span> $html";
if($htmlF) $html .= " <span class='miniF'>$htmlF</span>";
$html = str_replace(array('&quot;', '&lt;', '&gt;', '&amp;'), array('"', '<', '>', '&'), $html);
if($test_cache){
if($cache_ok){
$mode = ($cnt==1)? 'w+' : 'a+';
mkdirp($cachedir);
if ($handle = @fopen($cachefile, $mode)){
@fwrite($handle, "<Mini$cnt>$html</Mini$cnt>\n");fclose($handle);
}
}
elseif(file_exists($cachefile)) unlink($cachefile);
}
return $html;
}
function HandleMini($PN, $auth="read"){
global $Mini, $WorkDir, $UploadFileFmt, $UploadDir, $UploadPrefixFmt;
$page = RetrieveAuthPage($PN,$auth,1, READPAGE_CURRENT);# ask for pw if needed
$Mini['Px'] = (array)$Mini['Px']; $Mini['Py'] = (array)$Mini['Py'];
$q = preg_replace('/\\(:mini (.+):\\)/e', "MiniConf(PSS('$1'))", $page['text']);
$idx = intval(@$_REQUEST['idx']);
if(!isset($Mini['thumbs'][$idx])) $idx=0;
$upname = MakeUploadName($PN, $_REQUEST['upname']);
$mupname = "th0$idx---$upname.jpg";
$fpath = FmtPageName("$UploadFileFmt/$upname", $PN);
$mpath = FmtPageName("$UploadFileFmt/$mupname", $PN);
if(!file_exists($fpath)){Abort("? file '$fpath' not found."); exit;}
if(!file_exists($mpath) || filemtime($mpath)<filemtime($fpath)){
list($W, $H, $T) = @getimagesize($fpath);
if(!isset($Mini['ImTypes'][$T])){Abort("? format $T not supported."); exit;}
$f = $Mini['CreateFunction'];
$f($fpath,$mpath,$W,$H,$T,$idx);
}
$_REQUEST['upname'] = $mupname;
HandleDownload($PN);
}
function MiniConf($args){
global $Mini; $opt = ParseArgs($args);
if(is_array(@$opt[''])) $Mini['thumbs'] = $opt['']+$Mini['thumbs'];
for($i=0;$i<10;$i++) if(isset($opt["m$i"]) )$Mini['thumbs'][$i] = $opt["m$i"];
}
function MiniParseAttr($x,$d=null) # '100x100x50x50x90xffffff'
{
$y = explode('x', $x);
$y[5] = hexdec(@$y[5]);
if($d && $d!=$x) {
$d = MiniParseAttr($d);
foreach($d as $k=>$v)
if(!isset($y[$k])||$y[$k]=='') $y[$k] = $v;
}
ksort($y);
return array_map('intval', $y);
}
function MiniCreate($fpath,$mpath,$W,$H,$T,$idx){
global $Mini;
list($w,$h,$cx,$cy,$quality,$bg) = MiniParseAttr($Mini['thumbs'][$idx],$Mini['thumbs']['x']);
if($h==0)$h=round($w*$H/$W);
elseif($w==0)$w=round($h*$W/$H);
if($h*$w==0)$h=$w=100;
$imcopy = (function_exists('imagecopyresampled'))?'imagecopyresampled':'imagecopyresized';
$imcreate=(function_exists('imagecreatetruecolor'))?'imagecreatetruecolor':'imagecreate';
$fcreate = "imagecreatefrom".$Mini['ImTypes'][$T];
$img = $fcreate($fpath);
if (!@$img){return;}
$nimg = $imcreate($w, $h);
imagefill($nimg, 0, 0, imagecolorallocate($nimg, floor($bg/256/256), ($bg/256)%256, $bg%256));
$percent = max(1, min($H/$h, $W/$w));
$_h = round($percent*$h);
$_w = round($percent*$w);
$sW = min($W,$_w); #source width
$sH = min($H,$_h);
$sY = max(0, round(($H-$_h)*$cx/100));
$sX = max(0, round(($W-$_w)*$cy/100));
$tW = min($w, $W); #target width
$tH = min($h, $H);
$tY = max(0, round(($h-$H)/2));
$tX = max(0, round(($w-$W)/2));
$imcopy($nimg,$img,$tX,$tY,$sX,$sY,$tW,$tH,$sW,$sH);
imagedestroy($img);
if(function_exists('imageconvolution'))
imageconvolution($nimg, array(array(-1,-1,-1),array(-1,16,-1),array(-1,-1,-1)),8,0);
imagejpeg($nimg,$mpath,$quality);
imagedestroy($nimg);
}
function HandlePurgeMini($PN, $auth='edit'){
RetrieveAuthPage($PN, $auth, 1, READPAGE_CURRENT);
global $UploadDir, $UploadPrefixFmt, $Mini;
$udir = FmtPageName("$UploadDir$UploadPrefixFmt", $PN);
$cachefile = preg_quote(sprintf($Mini['CacheFilename'], $PN));
if ($dirp = @opendir($udir)){
while (($file=readdir($dirp)) !== false)
if (preg_match("/^(th\\d+---|$cachefile$)/", $file))
unlink("$udir/$file");
closedir($dirp);
}
Redirect($PN, $Mini['PurgeRedirectFmt']);
}
function MiniFixFName($PN, $x){
global $Mini, $UploadFileFmt;
$y = MakeUploadName($PN, $x);
if(!$Mini['FixFilenames']) return array($y, FmtPageName("$UploadFileFmt/$y", $PN));
$z = preg_replace(array_keys($Mini['FixFilenamePatterns']),array_values($Mini['FixFilenamePatterns']), $y);
$zpath = FmtPageName("$UploadFileFmt/$z", $PN);
foreach(array($x, $y) as $v){
$path = FmtPageName("$UploadFileFmt/$v", $PN);
if($path != $zpath && file_exists( $path ) ) @rename($path, $zpath);
}
return array($z, $zpath);
}
function MiniHeaderFmt($a=null){
global $Mini, $HTMLHeaderFmt;
if(!$a) $a = $Mini['LbFiles'];
foreach((array)$a as $f) {
if(preg_match('/^\\S+\\.js$/', $f))
SDVA($HTMLHeaderFmt, array($f => "<script type='text/javascript' src='{$Mini['LbUrl']}/$f'></script>\n"));
elseif(preg_match('/^\\S+\\.css$/', $f))
SDVA($HTMLHeaderFmt, array($f => "<link rel='stylesheet' href='{$Mini['LbUrl']}/$f' type='text/css' media='screen'/>\n"));
}
}
if(!function_exists('MatchNames')){function MatchNames($l,$p){return MatchPageNames($l,$p);}}