<?php if (!defined('PmWiki')) exit();
/**
	A thumbnail gallery generator for PmWiki
	Written by (c) Petko Yotov 2006-2007

	This script is POSTCARDWARE, if you like it or use it,
	please send me a postcard. Details at
	http://galleries.accent-bg.com/Thumblist

	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.

	Copyright 2006-2007 Petko Yotov http://5ko.free.fr
	Copyright 2004-2006 Patrick R. Michaud http://www.pmwiki.org
	Copyright 2006 Hagan Fox (haganfoxATusersDOTsourceforge.net)
*/
# Version date
$RecipeInfo['ThumbList']['Version'] = '2007-11-20';
$FmtPV['$ThumbListVersion'] = "'ThumbList-{$RecipeInfo['ThumbList']['Version']}'";

SDVA($ThumbList, array(
'Px' => 128,
'TableCols' => 0,
'TitleFormat' => "%f: %wx%h, %kk (%t)",
'CaptionFormat' => '',
'BgColor' => "#ffffff",//for shadows and transparent pictures
'RedoThumbs' => 0,// for debugging: 1 always; -1:never; 0:when needed
'Quality' => 90,
'Limit' => 0,
'MaxArea' => 0,
'LinkAdd' => '',
'Add' => '',// was $ThumbAdd
'LinkOriginal' => 0,// 1:always; -1:never; 0:when needed; 2:link to page
'ImageTplFmt' => '(:include {$FullName}-ImageTemplate {$Group}.ImageTemplate {$SiteGroup}.ImageTemplate:)',
'NoImageTplFmt' => '!! $[Displaying] {*$UpFile}
%p center% {*$PrevLink} [[{*$FullName}?action=browse | $[Back to gallery] ]] {*$NextLink}\\
Attach:{*$UpDirUpFile}
(:title {*$FullName} / {*$UpFile}:)',
'UseTmpl' => 0,
'Thread' => 1,
'ShowErrors' => 1,
'AttachLinks' => 1,
'PrevLink' => '<<',
'NextLink' => '>>',
'InlineCaptionCSS' => '',
'icapContainer' => 'div',# span or div
'AllowedUploadPages' => '*',
'PurgeRedirectFmt' => '{$PageUrl}?action=upload',
'FileExt' => 'jpg',
'ImageMagickExe' => '',
'DefaultCLTpl' => 'default',
'TrailPx' => 64,
'ImTypes' => array(1=>"gif",2=>"jpeg",3=>"png",15=>"wbmp",16=>"xbm"),
'tlmode'=> 0,
'HTMLpx'=> 1,

// '' => ,
));


SDVA($ThumbList['IMCLTpl'],
array('default'=>
'{%x} -size "{%W}x{%H}" "{%P}"[0] -thumbnail "{%w}x{%h}" -background {%c} -flatten -quality "{%q}" "{%p}"',
'shadow'=>'{%x} -size "{%W}x{%H}" "{%P}"[0] -thumbnail "{%w}x{%h}" -bordercolor white -border 3 -bordercolor grey60 -border 1 -background black ( +clone -shadow 60x3+2+2 ) +swap -background {%c} -flatten -resize "{%w}x{%h}!" -sharpen 1x1 -quality "{%q}" "{%p}"',
));

SDVA($HandleActions, array('imgtpl'=>'HandleImageTemplate',
	'purgethumbs'=>"HandlePurgeThumbnails",'createthumb'=>"HandleCreateThumb"));
SDVA($HandleAuth, array('purgethumbs' => 'edit'));
SDV($RobotActions['imgtpl'], 1);
SDV($RobotActions['createthumb'], 1);

// Trying to recover existing configurations...
// Do not rely on this, by 2008 it will be removed!
foreach($ThumbList as $k=>$v)
{
	$x = "Thumb$k";
	if(isset($$x)) $ThumbList[$k] = $$x;
}
if(isset($ThumbListUseTmpl))$ThumbList['UseTmpl'] = $ThumbListUseTmpl;
if(isset($ImageTemplateFmt))$ThumbList['ImageTplFmt'] = $ImageTemplateFmt;


Markup('thumblist', '<split',
  '/\\(:thumb(list)?\\s*(.*?):\\)/ei',
  "FmtThumbList(\$pagename,PSS('$2'),'$1')");
Markup('thumbgallery', '<thumblist',
  '/\\(:thumb(gallery)\\s*(.*?):\\)(.*?)\\(:thumbgalleryend:\\)/esi',
  "FmtThumbList(\$pagename,PSS('$2'),'$1', PSS('$3'))");
function FmtThumbList($pagename, $args, $suffix='', $list='')
{
	if(! function_exists('imagecreate') && ! $ThumbList['ImageMagickExe'])
		return ThumbReturn("PHP-GD image library not found. Exiting.", 2);
	global $UploadDir, $UploadPrefixFmt, $UploadUrlFmt, $TimeFmt, $EnableDirectDownload,
		$ThumbList, $ThumbList_ShowErrors;
	static $ThumbGalNumBase = 0;
	$ThumbGalNumBase++;

	$opt = ParseArgs($args);

	$currentpage = $pagename = MakePageName($pagename, $pagename);
	$captionfmt =IsEnabled($opt['captionfmt'], $ThumbList['CaptionFormat']);

	if($suffix){if (@$opt[''][0]) $pagename = MakePageName($pagename, $opt[''][0]);}
	else// "thumb" was used
	{
		if (! @$opt[''][0]) return ThumbReturn("No file specified.", 1);
		if(preg_match("!^(.*)\\/([^\\/]+)$!", $opt[''][0], $m) )
		{
			$pagename = MakePageName($pagename, $m[1]);
			$opt['name'] = $m[2];
		}
		else $opt['name'] = $opt[''][0];
		if($captionfmt)
		{
			$opt['cols'] = 1;
			$Width = 1;
		}
		else $opt['cols'] = 0;
	}
	$pagelist = MatchPageNames($pagename, FmtPageName($ThumbList['AllowedUploadPages'], $currentpage));
	if( @$pagelist[0] == '' )
	{ return ThumbReturn("$pagename does not match \$ThumbList['AllowedUploadPages'] permissions.", 1); }
	if ($pagename != $currentpage && !CondAuth($pagename,"read") ) { return ThumbReturn("No read permissions at $pagename.", 1); }

	$supercache = intval(@$opt['supercache']);
	$ThumbGalNum = ($supercache>999)? $supercache : $ThumbGalNumBase;

	if(!@$_POST['preview'] && !$ThumbList['RedoThumbs'] && $supercache)
	{
		$output = ThumbGetCache($currentpage, $pagename, $ThumbGalNum);
		if($output) return ThumbReturn($output);
	}
	if (@$opt['skip']) $skipmatch=ThumbFilePattern($opt['skip'], 'i');
	if (@$opt['name']) $pattern = ThumbFilePattern($opt['name'], 'i');

	$titlefmt = IsEnabled($opt['titlefmt'], $ThumbList['TitleFormat']);
	$thumbext = IsEnabled($opt['ext'], $ThumbList['FileExt']);
	if (intval(@$opt['px']) > 0 ) $Px = intval($opt['px']);
	elseif(intval(@$opt['width']))$Px = $Width = intval($opt['width']);
	else $Px = $ThumbList['Px'];
	$atarget = (@$opt['target'])? ' target="'.htmlspecialchars($opt['target']).'"' : '';
	$linkorig = IsEnabled($opt['link'], $ThumbList['LinkOriginal']);
	$usetpl = IsEnabled($opt['usetemplate'], $ThumbList['UseTmpl']);
	$trailstamp = $usetpl>0? ThumbGetCache($currentpage, $pagename, $ThumbGalNum, 2) : 0;
	$trail = ''; $trailcache = ($trailstamp>0)? 0:1;

	$thumbcols = IsEnabled($opt['cols'], $ThumbList['TableCols']);
	if($thumbcols==0)$captionfmt='';
	$icapcss = IsEnabled($opt['captioncss'], $ThumbList['InlineCaptionCSS']);
	$caption = @$opt['caption'];

	$maxarea = floatval(IsEnabled($opt['maxarea'], $ThumbList['MaxArea']))*1000000;
	$start = intval(@$opt['start']>0)? intval($opt['start']) : 1;
	$limit = IsEnabled($opt['limit'], $ThumbList['Limit']);
	$enableexif = ( preg_match("/([^%]|^)(%%)*%[MmWHTEFAIC]/",
		$titlefmt.$captionfmt.$ThumbList['LinkAdd'].$ThumbList['Add'])
		&& function_exists("exif_read_data"));
	$imcl = (@$opt['imcl']>'' && isset($ThumbList['IMCLTpl'][$opt['imcl']]))?
		$opt['imcl'] : '';
	$quiet = intval(@$opt['quiet']);//1:errors 2:attachlinks
	if($quiet%2 == 1)$ThumbList_ShowErrors=0;
	$tlmode = IsEnabled($opt['tlmode'], $ThumbList['tlmode']);

	$tableattributes = array("border", "cellpadding", "cellspacing", "rules", "style", "bgcolor", "align");
	$mytabattr = "";
	foreach($tableattributes as $k){if(isset($opt[$k])) $mytabattr.=" $k=\"".htmlspecialchars($opt[$k])."\"";}
	$mybgcolor = preg_match("/^#([0-9a-f]{6}|none)$/i", @$opt['bgcolor'])? $opt['bgcolor'] : $ThumbList['BgColor'];

	$uploaddir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
	$uploadurl = ThumbRelativeUrl( FmtPageName(IsEnabled($EnableDirectDownload, 1)
			? "$UploadUrlFmt$UploadPrefixFmt/"
			: "\$PageUrl?action=download&amp;upname=",
		$pagename));

	$filelist = array();
	if(!$suffix)$filelist[$opt['name']] = $opt['name'];
	elseif($suffix=='list' || $tlmode )
	{
		$dirp = @opendir($uploaddir);
		if($dirp)
		{
			while (($file=readdir($dirp)) !== false)
			{
				if ($file{0} == '.') continue;
				if (!preg_match("/\\.(jpe?g|png|gif|jpe|wbmp|xbm)$/i", $file)) continue;
				if (preg_match("/^th\\d+---/", $file)) continue;
				if (@$skipmatch && preg_match(@$skipmatch, $file)) continue;
				if (@$pattern && !preg_match($pattern, $file)) continue;
				$filelist[$file] = $file;
			}
			closedir($dirp);
			if(@$opt['shuffle']!=1) natcasesort($filelist);
		}
		elseif($suffix=='list') return ThumbReturn("Could not open '$uploaddir'.", 1);
	}
	if($suffix=='gallery')
	{
		preg_match_all("/^\s*(.+?\\.(?:jpe?g|png|gif|jpe|wbmp|xbm)) *(?:\\| *([^\\|\n]+?) *(?:\\| *(.*) *)?)?$/im", $list, $m, PREG_SET_ORDER);
		for($i=0; $i<count($m); $i++)
			$filelist[$m[$i][1]] = array(@$m[$i][2], @$m[$i][3]);

	}
	if(!count($filelist) ) return ThumbReturn("No pictures found.", 1);
	if(@$opt['shuffle'])
	{
		$ks = array_keys($filelist); shuffle($ks); $f2 = array();
		foreach($ks as $k)$f2[$k] = $filelist[$k];$filelist=$f2;
		$trailcache = 0;
		ThumbCacheName($currentpage, $uploadpage, $ThumbGalNum, 1, 1);
		NoCache();
	}
	$htmlpx = IsEnabled($opt['htmlpx'], $ThumbList['HTMLpx']);
	if($thumbcols)
	{
		$Px4 = $Px+4;
		$h = (@$Width)? '' : " height='$Px4'";
		$pad = (@$Width)? '2px' : '%dpx';
		$class = @$opt['class']? $opt['class'] : 'thumbtable';
		$outputstart = "<table class='$class'$mytabattr>";
		if($caption)$outputstart .= "<caption>$caption</caption>";
		$td1 = "<td class='thumbtd' align='center' valign='top'$h width='$Px4'><div class='img%s'"
		. ($htmlpx? " style='padding:$pad $pad;'":'')
		.">";
		$td2 = "</div><div class='caption'>";
		$td3 = "</div></td>\n";
	}
	elseif($icapcss>'')
	{
		$td1 = "<div class='thumbdiv'>";
		$td2 = $icapcss == 1? "<{$ThumbList['icapContainer']} class='caption'>" : "<{$ThumbList['icapContainer']} class='caption' style='$icapcss'>";
		$td3 = "</{$ThumbList['icapContainer']}></div>";
	}
	else {$td1 = " "; $td2 = $td3 = "";}

	$td=0;	$i=1; $output = $notfound='';
	foreach($filelist as $file=>$arr)
	{
		$filepath = "$uploaddir/$file";
		$info = @getimagesize($filepath);
		if(!is_array($arr))$arr='';
		if(!isset($ThumbList['ImTypes'][@$info[2]]))
		{
			$c = trim($arr[0])>'' ? " ([=".trim($arr[0])."=]) " : '';
			if($suffix!='list')$notfound .= "* [[Attach:$pagename/$file | $file$c]]\n";
			continue;
		}
		if($maxarea && $maxarea < $info[0]*$info[1]) continue;

		if($start>1 && $i<$start) { $i++; continue;}
		if($limit>0 && $i>=$limit+$start) { break;}

		$trail.="$file\n";

		$stat = stat($filepath);
		if($usetpl && $stat['mtime']>=$trailstamp && !@$opt['shuffle'])$trailcache = 1;

		$name = PUE("$uploadurl$file");

		if($thumbcols && $td%$thumbcols == 0)$output .= "<tr class='thumbtr'>\n";
		if(($thumbcols && $info[0]>$info[1]) || @$Width) // w > h
		{
			$imgh = round($Px * $info[1] / $info[0]);
			$imgw = $Px;
		}
		else { $imgh = $Px; $imgw = round($Px * $info[0] / $info[1]);}

		if($imgh>=$info[1] || $ThumbList['RedoThumbs']==-1)// the picture is not bigger than the thumb, display it
		{
			if($imgh>=$info[1])list($imgw, $imgh)= $info;
			$thumbname = $name;
		}
		else
		{
			$thumbprefix = "th$imgh---".substr($mybgcolor, 1). "--";
			$thumbpath = "$uploaddir/$thumbprefix$file.$thumbext";
			$thumbname = PUE("$uploadurl$thumbprefix$file.$thumbext");

			if($ThumbList['RedoThumbs']>0 || !file_exists($thumbpath) || filemtime($thumbpath)<$stat['mtime'] )
			{
				if($ThumbList['Thread'])
				{
					$thumbname = ThumbRelativeUrl(PUE(
						FmtPageName("\$PageUrl?action=createthumb&amp;imcl=$imcl&amp;upname=", $pagename)
						."$thumbprefix$file.$thumbext"));
					$opt['supercache'] = $supercache = 0;
					NoCache();
				}
				else CreateThumb($filepath, $thumbpath, $imgh, $info, $mybgcolor, $imcl);
			}
		}
		$ud = ($pagename == $currentpage)? '':"&amp;updir=$pagename";
		if($usetpl)$name = ThumbRelativeUrl( PUE(FmtPageName("\$PageUrl?action=imgtpl&amp;G=$ThumbGalNum$ud&amp;upname=$file", $currentpage)));

		$replArr = array(
			"%%" => "%",
			"%G" => $ThumbGalNum,
			"%f" => $file,
			"%w" => $info[0],
			"%h" => $info[1],
			"%b" => $stat['size'],
			"%k" => round($stat['size']/1024),
			"%t" => strftime($TimeFmt, $stat['mtime'])
		);
		if($enableexif)$replArr+=ThumbExif($filepath);
		## when inside an ImageTemplate, set pagevars for 1 pic and exit
		if(isset($opt['onlysetpagevars'])){ThumbSetPageVars($replArr); return;}
		$replArr+=array("%U" => $name, "%u" => $thumbname);
		$title= htmlspecialchars(strtr( ($arr[1])?$arr[1]:  $titlefmt, $replArr));
		$replArr+=array('%n'=>"\n", '%N'=>"<br/>");
		$text = strtr( ($arr[0])?$arr[0]:$captionfmt, $replArr);
		$thumbadd = strtr($ThumbList['Add'], $replArr);
		$thumblinkadd = strtr($ThumbList['LinkAdd'], $replArr);

		if($linkorig!=-1 && ($linkorig>0 || $thumbname != $name || $ThumbList['RedoThumbs']==-1))
		{
			$tmpurl = $linkorig==2? PageVar($pagename, '$PageUrl') : $name;
			$a2 = "</a>\n"; $a1 = "<a href='$tmpurl' class='thumblink'$atarget $thumblinkadd>";
		}
		else {$a1=$a2="";}

		$iscurrent = @$_GET['upname'] == $file ? ' current':'';
		$mytd1 = sprintf($td1, $iscurrent, round(($Px-$imgh)/2)+2, round(($Px-$imgw)/2)+2);
		$output .= "$mytd1$a1<img border='0' src='$thumbname' alt=\"$title\" title=\"$title\" class='thumbs$iscurrent'"
		.($htmlpx? " width='$imgw' height='$imgh'" : '')
		." $thumbadd/>$a2$td2$text$td3";

		$i++;$td++;
		if($thumbcols && $td%$thumbcols==0) $output .= "</tr>\n";
	}
	$output = trim($output);
	if(!$output && !$notfound) return ThumbReturn("Only ".($i-1)." images out of ".count($filelist)." files found but you set start=$start.", 1);
	if($thumbcols && $td%$thumbcols) $output .=  "</tr>\n";
	if($thumbcols && $output) $output = "$outputstart$output\n</table>\n";
	if($ThumbList['AttachLinks'] && $quiet<2 && strlen($notfound))
		$output .= MarkupToHTML($currentpage, $notfound);

	if(!$_POST['preview'])
	{
		if($supercache)ThumbSetCache($currentpage, $pagename, $ThumbGalNum, $output);
		if($usetpl>0 && $trailcache)ThumbSetCache($currentpage, $pagename, $ThumbGalNum, $trail, 1);
	}
	return ThumbReturn($output);
}
function ThumbReturn($x,$err=0)
{
	global $ThumbList_ShowErrors;
	if($ThumbList_ShowErrors==0 && $err==1) return;
	$a=$b=''; if($err){$a='<pre><b>ThumbList warning: </b>';$b='</pre>';}
	return '<:block>'. Keep("$a$x$b");
}
function ThumbSetPageVars($replArr)
{
	global $FmtPV;
	foreach($replArr as $k=>$v)
		$FmtPV["\$ThumbList_".$k{1}] = "'".htmlspecialchars($v, ENT_QUOTES)."'";
}
function CreateThumb($filepath, $thumbpath, $nh, $info, $bgc, $cl='')
{
	global $ThumbList;
	list($imgw, $imgh, $t) = $info;
	$nw = round($imgw * $nh / $imgh);
	if($ThumbList['ImageMagickExe'])
	{
		if($bgc == "#")$bgc="#ffffff";
		if($bgc == "#none")$bgc="none";
		$replArr = array(
			'x'=>$ThumbList['ImageMagickExe'], 'c'=>$bgc, 'q'=>$ThumbList['Quality'],
			'p'=>$thumbpath, 'P'=>$filepath, 'w'=>$nw, 'W'=>$imgw, 'h'=>$nh, 'H'=>$imgh,
		);
		$cl = IsEnabled($ThumbList['IMCLTpl'][$cl], $ThumbList['IMCLTpl'][$ThumbList['DefaultCLTpl']]);
		foreach($replArr as $k=>$v)
		{
			$cl = preg_replace("/\\{%$k\\}/", $v, $cl);
			$cl = preg_replace("/\\{%$k([+-]\\d+)\\}/e", "$w$1", $cl);
		}
		$cl = preg_replace("/\\{%RAND([+-]\\d+)([+-]\\d+)([\\*\\/]\\d+)?\\}/e", "mt_rand($1, $2)$3", $cl);
		
		$r = exec($cl, $o, $status);
		if(intval($status)!=0)
			Abort("convert returned <pre>$r\n".print_r($o, true)
			."'</pre> with a status $status.<br/> Command line was '$cl'.");
		return;
	}
	if($bgc == "#none")$bgc="#ffffff";/// TODO
	$rr = hexdec(substr($bgc, 1, 2) );
	$gg = hexdec(substr($bgc, 3, 2) );
	$bb = hexdec(substr($bgc, 5, 2) );
	$gd2 = function_exists('imagecreatetruecolor');
	$imcopy = ($gd2)?'imagecopyresampled':'imagecopyresized';
	$imcreate=($gd2)?'imagecreatetruecolor':'imagecreate';

	if(!isset($ThumbList['ImTypes'][$t])) return;
	$fcreate = "imagecreatefrom".$ThumbList['ImTypes'][$t];
	$img = $fcreate($filepath);
	if (!@$img){return;}

	$nimg = $imcreate($nw,$nh);
	if($t != 2)imagefill($nimg, 0, 0, imagecolorallocate($nimg, $rr, $gg, $bb));
	$imcopy($nimg,$img,0,0,0,0,$nw,$nh,$imgw,$imgh);
	imagedestroy($img);
	if(preg_match("/\\.png$/", $thumbpath))imagepng($nimg,$thumbpath,1);
	else imagejpeg($nimg,$thumbpath,$ThumbList['Quality']);
	imagedestroy($nimg);
}
function HandleCreateThumb($pagename, $auth="read")
{
	global $UploadDir, $UploadPrefixFmt, $ThumbList;
	$page = RetrieveAuthPage($pagename,$auth,1, READPAGE_CURRENT);//will ask for pw if needed
	$uploaddir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
	$t = $_REQUEST['upname']; $pt = "$uploaddir/$t";
	if(preg_match( "/^th(\\d+)---(?:([0-9a-f]{6}|none)--)?(.+)\\.(jpg|png)$/i", $t, $m ) )
	{
		$f = "$uploaddir/{$m[3]}";
		if(!file_exists($f) ) { Abort("?Source file $f not found."); return; }
		$info = @getimagesize($f);

		if($ThumbList['RedoThumbs'] == 1 || ! file_exists($pt) || filemtime($f)>filemtime($pt))//source newer than thumb
			CreateThumb($f, $pt, $m[1], $info, "#{$m[2]}", @$_REQUEST['imcl']);
		HandleDownload($pagename);
		exit();
	}
	Abort("?Unrecognized format: ThumbList upname='$t'.");
}
function HandlePurgeThumbnails($pagename, $auth='edit')
{
	global $UploadDir, $UploadPrefixFmt, $ThumbList;
	if (!CondAuth($pagename, $auth) ) { Abort("?Not enough permissions to purge all thumbs for $UploadPrefixFmt"); return; }
	$uploaddir = FmtPageName("$UploadDir$UploadPrefixFmt", $pagename);
	if ($dirp = @opendir($uploaddir))
	{
		while (($file=readdir($dirp)) !== false)
		{
			if (!preg_match("/^(th\\d+---|\\.thumblist)/", $file)) continue;
			unlink("$uploaddir/$file");
		}
		closedir($dirp);
	}
	if(@$_REQUEST['redirect']>'')Redirect(MakePageName($pagename, $_REQUEST['redirect']));
	else Redirect($pagename, $ThumbList['PurgeRedirectFmt']);
}
function ThumbCacheName($currentpage, $uploadpage, $n, $trail=0, $delete=0)
{
	global $UploadDir, $UploadPrefixFmt;
	$t = $trail? '-trail' : '';
	$f = FmtPageName("$UploadDir$UploadPrefixFmt/.thumblist$t.$currentpage.$n.cache", $uploadpage);
	if(!$delete) return $f;
	if(file_exists($f)) @unlink($f);
}
function ThumbGetCache($currentpage, $uploadpage, $n, $trail=0)
{
	global $PCache, $MessagesFmt;
	$ptime = $PCache[$currentpage]['time'];
	$t = ($trail)? '-trail' : '';
	$cachefile = ThumbCacheName($currentpage, $uploadpage, $n, $trail);
	if(file_exists($cachefile) && filemtime($cachefile) >= $ptime)
	{
		$MessagesFmt[] = "Getting cache for $currentpage, gallery$t $n<br />\n";
		if($trail==2) return filemtime($cachefile);
		if($handle = @fopen($cachefile, "r"))
		{
			$contents = @fread($handle, filesize($cachefile));
			fclose($handle);
		}
		if(@$contents>'') return ($trail? '' : "<!-- $cachefile -->\n").$contents;
	}
}
function ThumbSetCache($currentpage, $uploadpage, $n, $html, $trail=0)
{
	global $UploadDir, $UploadPrefixFmt, $MessagesFmt;
	$t = ($trail)? '-trail' : '';
	$MessagesFmt[] = "Caching gallery$t $n for $currentpage<br />\n";
	$cachefile = ThumbCacheName($currentpage, $uploadpage, $n, $trail);
	if ($handle = @fopen($cachefile, 'w+'))
	{
		@fwrite($handle, $html);
		fclose($handle);
	}
}
function ThumbFilePattern($x, $mod=''){return '/^'.str_replace(array("\\*","\\?","\\|"),array(".*",".","|"),preg_quote($x)).'$/'.$mod;}
function ThumbExif($filepath)
{
	$e = $exif = array();
	global $TimeFmt;
	$exif = @exif_read_data($filepath, 'EXIF', 1);
	$e['%M'] = @$exif['IFD0']['Make'];
	$e['%m'] = @$exif['IFD0']['Model'];
	$e['%W'] = IsEnabled($exif['COMPUTED']['Width'], @$exif['EXIF']['ExifImageWidth']);
	$e['%H'] = IsEnabled($exif['COMPUTED']['Height'], @$exif['EXIF']['ExifImageHeight']);
	$t = preg_replace('/^(\\d{4}):(\\d\\d):(\\d\\d.*)/', '$1-$2-$3', @$exif['EXIF']['DateTimeOriginal']);
	$e['%T'] = @$t? strftime($TimeFmt,strtotime($t)):'';
	$e['%E'] = @$exif['EXIF']['ExposureTime'];
	$e['%F'] = @$exif['EXIF']['FocalLength'];
	$e['%A'] = @$exif['COMPUTED']['ApertureFNumber'];
	$e['%I'] = @$exif['EXIF']['ISOSpeedRatings'];
	$e['%C'] = trim(@$exif['COMMENT']['0'].' '.@$exif['COMPUTED']['UserComment']);
	return $e;
}
## partly based on Hagan Fox's "HandleImageLink" from thumblink.php
function HandleImageTemplate($pagename)
{
	global $FmtV, $FmtPV, $PageStartFmt, $PageEndFmt, $ThumbList, $MetaRobots;
	$ThumbList['UseTmpl'] = 0;
	SDV($MetaRobots, 'index,follow');
	
	SDV($HandleImageTplFmt,array(&$PageStartFmt, '$PageText', &$PageEndFmt));
	PCache($pagename, RetrieveAuthPage($pagename, 'read',1, READPAGE_CURRENT));
	$uname=htmlspecialchars(@$_REQUEST['upname'], ENT_QUOTES);
	$pname=preg_replace("/^.*[\\.\\/]/", '', MakePageName($pagename, str_replace(".", "", $uname)));
	$udir =htmlspecialchars(@$_REQUEST['updir'], ENT_QUOTES);
	if($udir == '')$udir = $pagename;
	$ud = ($pagename == $udir)? '':"&updir=$udir";
	$G = intval(@$_REQUEST['G']);
	$a = explode("\n", ThumbGetCache($pagename, $udir, $G, 1));
	$key = @array_search($uname, $a);
	if($key!==false)$FmtPV['$CurrentThumbIndex'] = "'$key'";
	if(strlen(@$a[$key-1]))
	{
		$xx = $a[$key-1];
		$x = PUE($xx);
		$FmtPV['$PrevFile'] = "'$xx'";
		$FmtPV['$PrevLinkUrl'] = "'$pagename?action=imgtpl&G=$G$ud&upname=$x'";
		$FmtPV['$PrevLink'] = "'[[$pagename?action=imgtpl&G=$G$ud&upname=$x| {$ThumbList['PrevLink']} ]]'";
		$FmtPV['$PrevThumb'] = "'[[$pagename?action=imgtpl&G=$G$ud&upname=$x|(:thumb \"$udir/$xx\" px={$ThumbList['TrailPx']} link=-1:)]]'";
	}
	else $FmtPV['$PrevLinkUrl'] = "'$pagename?action=browse'";
	if(strlen(@$a[$key+1]))
	{
		$xx = $a[$key+1];
		$x = PUE($xx);
		$FmtPV['$NextFile'] = "'$xx'";
		$FmtPV['$NextLinkUrl'] = "'$pagename?action=imgtpl&G=$G$ud&upname=$x'";
		$FmtPV['$NextLink'] = "'[[$pagename?action=imgtpl&G=$G$ud&upname=$x| {$ThumbList['NextLink']} ]]'";
		$FmtPV['$NextThumb'] = "'[[$pagename?action=imgtpl&G=$G$ud&upname=$x|(:thumb \"$udir/$xx\" px={$ThumbList['TrailPx']} link=-1:)]]'";
	}
	else $FmtPV['$NextLinkUrl'] = "'$pagename?action=browse'";
	$FmtPV['$UpFile'] = "'$uname'";
	$FmtPV['$UpFilePage'] = "'$pname'";
	$FmtPV['$UpDir'] = "'$udir'";
	$FmtPV['$UpDirUpFile'] = "'$udir/$uname'";
	FmtThumbList($pagename, "\"$udir/$uname\" exif=1 onlysetpagevars=1");
	$FmtV['$PageText'] = MarkupToHTML($pagename,$ThumbList['ImageTplFmt']);
	if(!trim($FmtV['$PageText']))
	{	$FmtV['$PageText'] = MarkupToHTML($pagename,$ThumbList['NoImageTplFmt']);}
	PrintFmt($pagename, $HandleImageTplFmt);
}
function ThumbRelativeUrl($x)
{
	global $EnableLinkPageRelative;
	if(@$EnableLinkPageRelative) return preg_replace('!^[a-z]+://[^/]*!i', '', $x);
	return $x;
}