<?php
/*
 * werxgallery
 *
 * Version: 0.2-alpha
 * Author:  Dan Cech (dcech@phpwerx.net)
 * Website: http://www.phpwerx.net
 *
 * $Id: index.php,v 1.8 2005/11/09 00:43:21 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="/">mr2.phpwerx.net</a>
        / <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>';
    
    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>';
    
    $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>
    </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