<?php
/*
* werxgallery
*
* Version: 0.1-alpha
* Author: Dan Cech (dcech@phpwerx.net)
* Website: http://www.phpwerx.net
*
* $Id: index.php,v 1.6 2005/05/03 15:48:53 dcech Exp $
*/
if (isset($_REQUEST['source'])) {
highlight_file(__FILE__);
exit;
}
define('GALLERY_TITLE','Photos');
define('IMG_LIB','imagemagick');
// define('IMG_LIB','gd2');
define('IMAGEMAGICK_PATH', '');
define('IMAGEMAGICK_MONTAGE',IMAGEMAGICK_PATH.'montage');
define('IMAGEMAGICK_CONVERT',IMAGEMAGICK_PATH.'montage');
define('THUMB_HEIGHT',100);
define('THUMB_WIDTH', 120);
define('THUMB_TYPE', 'jpeg');
define('THUMB_BG_R', 255);
define('THUMB_BG_G', 255);
define('THUMB_BG_B', 255);
define('DEFAULT_TYPE','jpeg');
define('BASE_PATH',realpath(getcwd()));
define('DIR_SEP', strpos(BASE_PATH,'/') === FALSE ? '\\' : '/');
error_reporting(E_ALL);
ini_set('memory_limit','20M');
$gallery = new gallery();
$gallery->display();
class gallery
{
var $exts = array(
'.jpg' => 'jpeg',
'.jpeg' => 'jpeg',
'.gif' => 'png',
'.png' => 'png',
'.bmp' => 'png'
);
var $sizes = array(
'800x600',
'1024x768',
'full'
);
var $base;
var $path;
var $uri;
var $rel;
var $dirs;
var $imgs;
var $mtime;
var $use_cache = true;
function gallery()
{
// start with directory part of PHP_SELF
$this->base = strrev(strchr(strrev($_SERVER['PHP_SELF']),'/'));
// get request URI
$this->uri = urldecode($_SERVER['REQUEST_URI']);
if (strpos($this->uri,'?') !== false) {
$this->uri = substr($this->uri,0,strpos($this->uri,'?'));
}
// check for thumb request
if (preg_match('/^(.+\/)?(thumbs?\/)([^\/]+)$/',$this->uri,$matches)) {
$this->uri = $matches[1];
$_REQUEST['thumb'] = $matches[3];
// check for image page request
} elseif (preg_match('/^(.+?\/)?((800x600|1024x768|full)\/)?([^\/]+).html$/',$this->uri,$matches)) {
$this->uri = $matches[1];
$_REQUEST['view'] = $matches[4];
if (!empty($matches[3])) {
$_REQUEST['size'] = $matches[3];
}
// check for image request
} elseif (preg_match('/^(.+?\/)?((800x600|1024x768|full)\/)?([^\/]+)$/',$this->uri,$matches)) {
$this->uri = $matches[1];
$_REQUEST['img'] = $matches[4];
if (!empty($matches[3])) {
$_REQUEST['size'] = $matches[3];
}
}
$this->rel = substr($this->uri,strlen($this->base));
$this->path = realpath('./'.$this->rel).DIR_SEP;
// check it is in the base
if (substr($this->path,0,strlen(BASE_PATH)) != BASE_PATH) {
exit('Invalid Directory');
}
// try to open the directory
if (!is_dir($this->path) || !$dh = opendir($this->path)) {
exit('Could Not Open Directory');
}
$this->dirs = array();
$this->imgs = array();
while (($file = readdir($dh)) !== false) {
if (substr($file,0,1) == '.') {
continue;
}
if (is_dir($this->path.$file)) {
$this->dirs[$file] = $file;
continue;
}
$ext = strtolower(strrchr($file,'.'));
if (isset($this->exts[$ext])) {
$this->imgs[$file] = $file;
}
}
closedir($dh);
natsort($this->dirs);
natsort($this->imgs);
$this->mtime = filemtime(__FILE__);
}
function display()
{
// figure out what we're trying to do
if (isset($_REQUEST['thumb'])) {
if (isset($this->imgs[$_REQUEST['thumb']])) {
return $this->thumb($_REQUEST['thumb']);
}
}
if (!isset($_REQUEST['size']) || !in_array($_REQUEST['size'],$this->sizes)) {
$_REQUEST['size'] = reset($this->sizes);
}
if (isset($_REQUEST['img'])) {
if (isset($this->imgs[$_REQUEST['img']])) {
return $this->image($_REQUEST['img'],$_REQUEST['size']);
}
}
if (isset($_REQUEST['view'])) {
if (isset($this->imgs[$_REQUEST['view']])) {
return $this->show_img($_REQUEST['view'],$_REQUEST['size']);
} else {
add_message('Invalid Image');
}
}
return $this->show_dir();
}
function show_img($img,$size)
{
$dim = getimagesize($this->path.$img);
$fsize = filesize($this->path.$img);
$details = array(
'width' => $dim[0],
'height' => $dim[1],
'fsize' => $fsize,
'dsize' => $size
);
print_header($this->base);
print_breadcrumb($this->base,$this->rel);
print_messages();
print_image($img,$this->imgs,$this->sizes,$details);
print_footer();
}
function show_dir()
{
print_header($this->base);
print_breadcrumb($this->base,$this->rel);
print_messages();
print_directories($this->dirs);
print_thumbnails($this->imgs);
print_footer();
}
function thumb($imgfile)
{
$name = strrev(strchr(strrev($imgfile),'.')).THUMB_TYPE;
if ($this->use_cache) {
@chmod($this->path,0775);
$path = $this->path.'.thumbs'.DIR_SEP;
if (!is_dir($path)) {
@mkdir($path);
}
if (@file_exists($path.$name) && filesize($path.$name) > 0) {
$mtime = filemtime($path.$name);
if ($mtime > filemtime($this->path.$imgfile) && $mtime > $this->mtime) {
$this->header(THUMB_TYPE);
readfile($path.$name);
exit;
}
}
if (@touch($path.$name)) {
thumbnail_image($this->path.$imgfile,THUMB_WIDTH,THUMB_HEIGHT,THUMB_TYPE,$path.$name);
$this->header(THUMB_TYPE);
readfile($path.$name);
exit;
}
}
$this->header(THUMB_TYPE);
thumbnail_image($this->path.$imgfile,THUMB_WIDTH,THUMB_HEIGHT,THUMB_TYPE);
exit;
}
function image($imgfile,$size)
{
$ext = strtolower(strrchr($imgfile,'.'));
if (isset($this->exts[$ext])) {
$type = $this->exts[$ext];
} else {
$type = DEFAULT_TYPE;
}
if ($size == 'full') {
$this->header($type);
readfile($this->path.$imgfile);
exit;
}
list($w,$h) = explode('x',$size,2);
$name = strrev(strchr(strrev($imgfile),'.')).$type;
if ($this->use_cache) {
@chmod($this->path,0775);
$path = $this->path.'.'.$size.DIR_SEP;
if (!is_dir($path)) {
@mkdir($path);
}
if (@file_exists($path.$name)) {
$mtime = filemtime($path.$name);
if ($mtime > filemtime($this->path.$imgfile) && $mtime > $this->mtime) {
$this->header($type);
readfile($path.$name);
exit;
}
}
if (@touch($path.$name)) {
resize_image($this->path.$imgfile,$w,$h,$type,$path.$name);
$this->header($type);
readfile($path.$name);
exit;
}
}
$this->header($type);
resize_image($this->path.$imgfile,$w,$h,$type);
exit;
}
function header($type)
{
// return false if headers already sent
if (headers_sent()) {
return false;
}
// disable php automatic cache control
session_cache_limiter('none');
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
$http_date_format = 'D, d M Y H:i:s \G\M\T';
$gm_date = gmdate('U');
$http_date = gmdate($http_date_format,$gm_date);
// set date header
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18
header('Date: '. $http_date);
// set content expiration 30 days in the future
header('Expires: '. gmdate($http_date_format,mktime(0,0,0,gmdate('m',$gm_date),gmdate('d',$gm_date)+30,gmdate('Y',$gm_date))));
// set content last modified on the first of last month
header('Last-Modified: '. gmdate($http_date_format,mktime(0,0,0,gmdate('m',$gm_date)-1,1,gmdate('Y',$gm_date))));
// HTTP/1.1
header('Cache-Control: public');
switch ($type) {
case 'jpeg':
$mimetype = 'image/jpeg';
break;
case 'png':
default:
$mimetype = 'image/png';
}
header('Content-Type: '.$mimetype);
}
}
/*** FUNCTIONS ***/
function print_header($base)
{
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Photo Gallery</title>
<link rel="stylesheet" type="text/css" href="'. $base .'styles.css" />
</head>
<body>';
}
function print_footer()
{
echo '
<div class="footer">
werxgallery 0.1-alpha <a href="?source=1">source</a>
</div>
</body>
</html>';
}
function print_breadcrumb($base,$rel)
{
echo '
<div class="breadcrumb">
<a href="'.htmlentities($base).'">'.htmlentities(GALLERY_TITLE).'</a>';
$url = $base;
$folders = preg_split('/(\/|\\\)/',$rel,0,PREG_SPLIT_NO_EMPTY);
foreach ($folders as $key => $val) {
$url .= $val .'/';
echo ' / <a href="'. htmlentities($url) .'">'. htmlentities(str_replace('_',' ',$val)) .'</a>';
}
echo '
</div>';
}
function print_directories($subdirs)
{
if (!is_array($subdirs) || empty($subdirs)) {
return;
}
echo '
<div class="subdirs">
<h2>Galleries</h2>
<ul>';
foreach ($subdirs as $subdir) {
echo '
<li><a href="'. htmlentities($subdir) .'/">'. htmlentities(str_replace('_',' ',$subdir)) .'</a></li>';
}
echo '
</ul>
</div>';
}
function print_thumbnails($images)
{
if (!is_array($images) || empty($images)) {
return;
}
echo '
<div class="thumbs">
<h2>Images</h2>
<ul>';
foreach ($images as $image) {
echo '
<li><a href="'. view_url($image) .'"><img src="'. thumb_url($image) .'" width="'. THUMB_WIDTH .'" height="'. THUMB_HEIGHT .'" title="'. htmlentities($image) .'" /></a></li>';
}
echo '
</ul>
<div class="clearer"></div>
</div>';
}
function thumb_url($image)
{
if (!empty($_SERVER['REDIRECT_STATUS'])) {
global $gallery;
return htmlentities($gallery->base . $gallery->rel .'thumb/'. $image);
}
return htmlentities('?thumb='. urlencode($image));
}
function img_url($image,$size = NULL)
{
if (!empty($_SERVER['REDIRECT_STATUS'])) {
global $gallery;
$url = $gallery->base . $gallery->rel;
if (!empty($size)) {
$url .= $size .'/';
}
$url .= $image;
} else {
$url = '?img='. urlencode($image);
if (!empty($size)) {
$url .= '&size='. $size;
}
}
return htmlentities($url);
}
function view_url($image,$size = NULL)
{
if (!empty($_SERVER['REDIRECT_STATUS'])) {
global $gallery;
$url = $gallery->base . $gallery->rel;
if (!empty($size)) {
$url .= $size .'/';
}
$url .= $image .'.html';
} else {
$url = '?view='. urlencode($image);
if (!empty($size)) {
$url .= '&size='. $size;
}
}
return htmlentities($url);
}
function print_image($img,$files,$sizes,$details)
{
echo '
<div class="image">
<h2>'. htmlentities($img) .'</h2>';
if ($details['dsize'] == 'full') {
$w = $details['width'];
$h = $details['height'];
} else {
list($w,$h) = explode('x',$details['dsize'],2);
if (in_array('full',$sizes) && $w > $details['width'] && $h > $details['height']) {
$details['dsize'] = 'full';
$w = $details['width'];
$h = $details['height'];
} elseif ($size = calculate_image_size($img,$w,$h,$details)) {
$w = $size['w'];
$h = $size['h'];
}
}
echo '
<div class="img"><img src="'. img_url($img,$details['dsize']) .'" width="'.$w.'" height="'.$h.'" /></div>';
$out_sizes = array();
foreach ($sizes as $size) {
if ($size == 'full') {
$label = 'full';
} else {
list($w,$h) = explode('x',$size,2);
if ($w > $details['width'] && $h > $details['height']) {
continue;
}
$label = $w .' x '. $h;
}
if ($size == $details['dsize']) {
$out_sizes[] = $label;
} else {
$out_sizes[] = '<a href="'. view_url($img,$size) .'">'. $label .'</a>';
}
}
if (!empty($out_sizes)) {
echo '
<div class="sizes">
'. implode(' ',$out_sizes) .'
</div>';
}
echo '
<div class="details">
'. $details['width'] .' x '. $details['height'] .' px - '. hsize($details['fsize']) .'
</div>';
$files = array_values($files);
$pos = array_search($img,$files);
$first = $files[0];
$last = $files[count($files) - 1];
$prev = isset($files[$pos - 1]) ? $files[$pos - 1] : NULL;
$next = isset($files[$pos + 1]) ? $files[$pos + 1] : NULL;
echo '
<div class="navigation">';
if ($img != $first) {
echo '
<a href="'. view_url($first,$details['dsize']) .'" title="first">I<</a> <a href="'. view_url($prev,$details['dsize']) .'" title="previous"><<</a>';
} else {
echo '
I< <<';
}
// echo ' <a href=".">index</a> ';
echo '
'. ($pos + 1) .' of '. count($files) .' ';
if ($img != $last) {
echo '
<a href="'. view_url($next,$details['dsize']) .'" title="next">>></a> <a href="'. view_url($last,$details['dsize']) .'" title="last">>I</a>';
} else {
echo '
>> >I';
}
echo '
</div>';
echo '
<div class="forum_code">
'. preg_replace('/ /','+','[url=http://'. $_SERVER['SERVER_NAME'] . view_url($img,$details['dsize']) .'][img]http://' . $_SERVER['SERVER_NAME'] . thumb_url($img) .'[/img][/url]') .'
</div>';
echo '
<div class="forum_code">
'. htmlentities('<a href="http://'. $_SERVER['SERVER_NAME'] . img_url($img,$details['dsize']) .'" rel="lightbox['. date('Y-m-d') .']" title="'. htmlentities($img) .'"><img src="http://' . $_SERVER['SERVER_NAME'] . thumb_url($img) .'" alt="'. htmlentities($img) .'" width="'. THUMB_WIDTH .'" height="'. THUMB_HEIGHT .'" /></a>') .'
</div>';
echo '
</div>';
}
function add_message($message = NULL)
{
static $messages = array();
if (!empty($message)) {
$messages[] = $message;
}
return $messages;
}
function print_messages()
{
$messages = add_message();
if (empty($messages)) {
return;
}
echo '
<div class="messages">';
foreach ($messages as $message) {
echo '
'. $message .'<br />';
}
echo '
</div>';
}
function calculate_image_size($imgfile,$w = NULL,$h = NULL,$details = NULL)
{
if (!isset($w)) {
$w = THUMB_WIDTH;
}
if (!isset($h)) {
$h = THUMB_HEIGHT;
}
if (is_array($details)) {
$s_w = $details['width'];
$s_h = $details['height'];
} else {
if (!file_exists($imgfile)) {
return false;
}
$size = getimagesize($imgfile);
$s_w = $size[0];
$s_h = $size[1];
}
$s_aspect = $s_w / $s_h;
$d_aspect = $w / $h;
if (($s_aspect < 1 && $d_aspect > 1) || ($s_aspect > 1 && $d_aspect < 1)) {
$t = $w;
$w = $h;
$h = $t;
}
$ratio = min($w / $s_w,$h / $s_h);
return array(
'w' => round($s_w * $ratio),
'h' => round($s_h * $ratio)
);
}
function thumbnail_image($imgfile,$w = NULL,$h = NULL,$format = 'png',$destfile = NULL)
{
if (!file_exists($imgfile)) {
return false;
}
if (!isset($w)) {
$w = THUMB_WIDTH;
}
if (!isset($h)) {
$h = THUMB_HEIGHT;
}
switch (strtolower(IMG_LIB)) {
case 'imagemagick':
return _thumbnail_image_imagemagick($imgfile,$w,$h,$format,$destfile);
case 'gd2':
return _thumbnail_image_gd2($imgfile,$w,$h,$format,$destfile);
}
return false;
}
function resize_image($imgfile,$w = NULL,$h = NULL,$format = 'png',$destfile = NULL)
{
if (!isset($w)) {
$w = THUMB_WIDTH;
}
if (!isset($h)) {
$h = THUMB_HEIGHT;
}
if (!$size = calculate_image_size($imgfile,$w,$h)) {
return false;
}
$w = $size['w'];
$h = $size['h'];
switch (strtolower(IMG_LIB)) {
case 'imagemagick':
return _resize_image_imagemagick($imgfile,$w,$h,$format,$destfile);
case 'gd2':
return _resize_image_gd2($imgfile,$w,$h,$format,$destfile);
}
return false;
}
function _thumbnail_image_imagemagick($imgfile,$w = NULL,$h = NULL,$format = 'png',$destfile = NULL)
{
$cmd = IMAGEMAGICK_MONTAGE
. ' -size '. $w .'x'. $h
. ' -geometry '. $w .'x'. $h
. ' -background '. escape_arg('rgb('. THUMB_BG_R .','. THUMB_BG_G .','. THUMB_BG_B .')')
. ' '. escape_arg($imgfile)
. ' ';
if (isset($destfile)) {
switch (strtolower($format)) {
case 'jpg':
case 'jpeg':
$cmd .= escape_arg('jpeg:'.$destfile);
exec($cmd);
break;
case 'png':
$cmd .= escape_arg('png:'.$destfile);
exec($cmd);
break;
default:
return false;
}
} else {
switch (strtolower($format)) {
case 'jpg':
case 'jpeg':
$cmd .= 'jpeg:-';
passthru($cmd);
break;
case 'png':
$cmd .= 'png:-';
passthru($cmd);
break;
default:
return false;
}
}
return true;
}
function _resize_image_imagemagick($imgfile,$w = NULL,$h = NULL,$format = 'png',$destfile = NULL)
{
$cmd = IMAGEMAGICK_CONVERT
. ' -size '. $w .'x'. $h
. ' -geometry '. $w .'x'. $h
. ' '. escape_arg($imgfile)
. ' ';
if (isset($destfile)) {
switch (strtolower($format)) {
case 'jpg':
case 'jpeg':
$cmd .= escape_arg('jpeg:'.$destfile);
exec($cmd);
break;
case 'png':
$cmd .= escape_arg('png:'.$destfile);
exec($cmd);
break;
default:
return false;
}
} else {
switch (strtolower($format)) {
case 'jpg':
case 'jpeg':
$cmd .= 'jpeg:-';
passthru($cmd);
break;
case 'png':
$cmd .= 'png:-';
passthru($cmd);
break;
default:
return false;
}
}
return true;
}
function _thumbnail_image_gd2($imgfile,$w = NULL,$h = NULL,$format = 'png',$destfile = NULL)
{
$size = getimagesize($imgfile);
$s_w = $size[0];
$s_h = $size[1];
$w_ratio = $w / $s_w;
$h_ratio = $h / $s_h;
// source image is smaller than dest image
if (min($h_ratio,$w_ratio) >= 1) {
$d_w = $s_w;
$d_h = $s_h;
$d_x = floor(($w - $s_w) / 2);
$d_y = floor(($h - $s_h) / 2);
// same aspect ratio
} elseif ($w_ratio == $h_ratio) {
$d_w = $w;
$d_h = $h;
$d_x = 0;
$d_y = 0;
// different aspect ratio
} elseif ($w_ratio < $h_ratio) {
$d_w = $w;
$d_h = floor($s_h * $w_ratio);
$d_x = 0;
$d_y = floor(($h - $d_h) / 2);
} else {
$d_w = floor($s_w * $h_ratio);
$d_h = $h;
$d_x = floor(($w - $d_w) / 2);
$d_y = 0;
}
switch ($size[2]) {
case 1: // GIF
$src = imagecreatefromgif($imgfile);
break;
case 2: // JPEG
check_jpeg($imgfile);
$src = imagecreatefromjpeg($imgfile);
break;
case 3: // PNG
$src = imagecreatefrompng($imgfile);
break;
default:
$src = imagecreatefromstring(file_get_contents($imgfile));
}
if (!is_resource($src)) {
return false;
}
$dest = imagecreatetruecolor($w,$h);
if (!is_resource($dest)) {
return false;
}
imageantialias($dest,TRUE);
$bg = imagecolorallocate($dest,THUMB_BG_R,THUMB_BG_G,THUMB_BG_B);
imagefill($dest,0,0,$bg);
imagecopyresampled($dest,$src,$d_x,$d_y,0,0,$d_w,$d_h,$s_w,$s_h);
if (isset($destfile)) {
switch (strtolower($format)) {
case 'jpg':
case 'jpeg':
imagejpeg($dest,$destfile);
break;
case 'png':
imagepng($dest,$destfile);
break;
default:
return false;
}
} else {
switch (strtolower($format)) {
case 'jpg':
case 'jpeg':
imagejpeg($dest);
break;
case 'png':
imagepng($dest);
break;
default:
return false;
}
}
return true;
}
function _resize_image_gd2($imgfile,$w = NULL,$h = NULL,$format = 'png',$destfile = NULL)
{
$size = getimagesize($imgfile);
$s_w = $size[0];
$s_h = $size[1];
switch ($size[2]) {
case 1: // GIF
$src = imagecreatefromgif($imgfile);
break;
case 2: // JPEG
check_jpeg($imgfile);
$src = imagecreatefromjpeg($imgfile);
break;
case 3: // PNG
$src = imagecreatefrompng($imgfile);
break;
default:
$src = imagecreatefromstring(file_get_contents($imgfile));
}
if (!is_resource($src)) {
return false;
}
$dest = imagecreatetruecolor($w,$h);
if (!is_resource($dest)) {
return false;
}
imageantialias($dest,TRUE);
imagecopyresampled($dest,$src,0,0,0,0,$w,$h,$s_w,$s_h);
if (isset($destfile)) {
switch (strtolower($format)) {
case 'jpg':
case 'jpeg':
imagejpeg($dest,$destfile);
break;
case 'png':
imagepng($dest,$destfile);
break;
default:
return false;
}
} else {
switch (strtolower($format)) {
case 'jpg':
case 'jpeg':
imagejpeg($dest);
break;
case 'png':
imagepng($dest);
break;
default:
return false;
}
}
return true;
}
/**
* Format file size in a human-readable way
* such as "xx Megabytes" or "xx Mo"
*
* @author Andrea Paleni <andreaSPAMLESS_AT_SPAMLESScriticalbit.com>
* @version 1.0
* @param int bytes is the size
* @param bool base10 enable base 10 representation, otherwise
* default base 2 is used
* @param int round number of fractional digits
* @param array labels strings associated to each 2^10 or
* 10^3(base10==true) multiple of base units
*/
function hsize($bytes,$base10 = false,$round = 0,$labels = array('bytes','Kb','Mb','Gb'))
{
if ($bytes <= 0 || !is_array($labels) || empty($labels)) {
return null;
}
$step = $base10 ? 3 : 10;
$base = $base10 ? 10 : 2;
$log = (int)(log10($bytes)/log10($base));
krsort($labels);
foreach ($labels as $p => $lab) {
$pow = $p * $step;
if ($log >= $pow) {
$text = round($bytes/pow($base,$pow),$round).$lab;
break;
}
}
return $text;
}
function check_jpeg($f,$fix = true)
{
# [070203]
# check for jpeg file header and footer - also try to fix it
if (false !== (@$fd = fopen($f,'r+b'))) {
if (fread($fd,2) == chr(255).chr(216)) {
fseek ($fd,-2,SEEK_END);
if (fread($fd,2) == chr(255).chr(217)) {
fclose($fd);
return true;
}
if ($fix && fwrite($fd,chr(255).chr(217))) {
fclose($fd);
return true;
}
}
fclose($fd);
}
return false;
}
function escape_arg($arg)
{
if (PHP_OS == 'Windows' || PHP_OS == 'WINNT') {
return '"'. preg_replace('/(["<>%|&])/','\\$1',$arg) .'"';
}
return escapeshellarg($arg);
}
// end of script