Location: PHPKode > scripts > Shampoo > shampoo/functions.php
<?php
class Album {
  public function __construct($album, $images, $fish) {
    $this->name = $album;
    $this->title = PRETTYTITLES === true ? makePrettyTitle($album) : $album;
    $this->title = $album;
    foreach ($images as $image) {
      if (is_dir($image)) continue;
      $baseimg = basename($image);
      $imgname = strip_ext($baseimg);
      if (is_readable("$album/thumbs/$imgname.png") || isValidImage($image)) $this->images[] = $baseimg;
    }
    $this->imagecount = count($this->images);
    if (!$fish || $fish === $album) $this->addCaptions($album);
    if (is_array($GLOBALS['passwords']) && $GLOBALS['passwords'][$album]) $this->password = $GLOBALS['passwords'][$album];
  }

  public function addCaptions($album) {
    $file = @file($album . '/' . $album . '.txt', FILE_SKIP_EMPTY_LINES);
    if ($file) {
      foreach ($file as $line) {
        $bits = parseLine($line);
        if ($bits) $data[$bits[0]] = $bits[1];
      }
    }
    foreach ((array)$this->images as $image) { // cast to array if $this->images is empty to stop foreach throwing an error
      if ($data[$image]) $this->captions[$image] = ampquot($data[$image]);
      elseif (FNORD === true) $this->captions[$image] = $GLOBALS['fnord']->fnord();
      else $this->captions[$image] = $image;
    }
  }
}

class Shampoo {
  public function __construct($fish) {
    $this->title = $GLOBALS['title'];
    $ignore = $GLOBALS['folderstoignore'];
    $albums = glob("*", GLOB_ONLYDIR);
    if (is_array($ignore)) $albums = array_diff($albums, $ignore);
    if (!in_array($fish, $albums)) unset($fish);
    foreach ($albums as $album) {
      if (is_readable($album)) {
        $this->albumlist[] = $album;
        $images = (array)glob("$album/*.*");
        if ($fish === $album && !$images) unset($fish);
        $this->$album = new Album($album, $images, $fish);
      }
    }
    if ($fish && $this->$fish && $this->$fish->imagecount > 0) $this->album = $fish;
    else unset($fish);
    if (is_readable(INDEX)) {
      foreach (file(INDEX, FILE_SKIP_EMPTY_LINES) as $line) {
        $bits = parseLine($line);
        if ($bits && $bits[0] && $this->$bits[0]) {
          $this->$bits[0]->title = $bits[1] ? trim(htmlspecialchars($bits[1], ENT_COMPAT)) : trim($bits[0]);
          $this->$bits[0]->description = ampquot(trim($bits[2]));
        }
      }
    }
    switch(SORTBY) {
      case 'title': usort($this->albumlist, array($this, 'titleSort')); break;
      case 'name': sort($this->albumlist); break;
      case 'date': usort($this->albumlist, 'dateSort'); break;
    }
  }
  
  public function makeMenu() {
    foreach ($this->albumlist as $album) {
      $html .= '      <li><a href="' . $album . '/"';
      if ($this->album === $album) $html .= ' class="current"';
      $pic = $this->$album->imagecount === 1 ? 'picture' : 'pictures';
      $html .= ' title="' . $this->$album->imagecount . $pic . '">' . $this->$album->title;
      if ($this->$album->password && !$_SESSION['access'][$album]) $html .= ' <img src="img/lock.gif" width="8" height="10" title="Private album - you will be asked for a password" alt="(Private)">';
      $html .= "</a></li>\n";
    }
    $this->register_var('albumlist', ltrim($html));
  }

  public function showList() {
    $this->register_var('content', (string)$GLOBALS['toptext'] . "\n  <ul id=\"albumarray\">\n");
    $listcount = 0;
    foreach ($this->albumlist as $key => $album) {
      if ($this->$album->password && !$_SESSION['access'][$album]) continue;
      $icount = $this->$album->imagecount;
      $desc = $this->$album->description;
      $images = (array)$this->$album->images; // cast to array so shuffle won't fail on this being null if no images in album
      $title = $this->$album->title;
      if (RANDOM === true) shuffle($images);
      $cls = $listcount % 2 ? ' class="odd"' : '';
      $listcount++;
      $howmany = $icount === 1 ? 'One picture' : "$icount pictures";
      $buff = "    <li$cls>
      <h3><a href=\"{$this->$album->name}/\" title=\"Open $title\">$title <span>&raquo; Open album</span></a></h3>
      <p class=\"imagecount\">$howmany</p>\n";
      if ($icount > 0) {
        $buff .= "      <div>\n";
        $classextra = '';
        foreach ($images as $key => $image) {
          $caption = $this->$album->captions[$image];
          $imgname = strip_ext($image);
          $thumbpath = "$album/thumbs/$imgname.png";
          if (!file_exists($thumbpath) && !createThumb($album, $image)) continue;
          $title = htmlspecialchars(strip_tags($caption), ENT_COMPAT, 'UTF-8');
          if ($key > 3) $classextra = ' thumbhide';
          $size = @getimagesize($thumbpath);
          $buff .= '        <a href="' . "$album/" . fakeUrl($image) . '" title="' . $title . '" rel="' . $album . '" class="thickbox' . $classextra . '"><img src="' . $thumbpath . '" alt="' . truncate($title) . '" ' . $size[3] . "></a>\n        <p>$caption</p>\n";
          if ($key === PERALBUM - 1) break;
        }
        $buff .= "      </div>\n";
      }
      else $buff .= "      <p>This album is devoid of images!</p>\n";
      if (DESCRIPTIONS === true && $desc) {
        $c = strlen($desc) > 750 ? ' class="columnar"' : '';
        $buff .= "      <p$c>$desc</p>\n";
      }
      $this->register_var('content', $buff . "    </li>\n");
    }
    $this->register_var('content', "  </ul>\n");
  }

  public function albumate($fish) {
    $album = $this->album;
    if ($this->$album->password) {
      if ($_POST['password']) {
        if (!$_SESSION['access']) $_SESSION['access'] = array();
        if ($_POST['password'] === $this->$album->password) $_SESSION['access'][$album] = true;
        else $pass = false;
      }
      if (!$_SESSION['access'][$album]) {
        $this->makeHeadLink('up', './', 'List of albums');
        $this->register_var('header', '<a href="./" title="Front page">' . $this->title . '</a> &raquo; ' . $this->{$this->album}->title);
        $html = "  <form action=\"$album/\" method=\"post\" id=\"blockade\">\n";
        if ($pass === false) $html .= '    <p class="error">Wrong password entered. Please note it is case sensitive.</p>'."\n";
        $html .= "    <p>This is a private album. To see it you must enter a password.</p>\n    <label>Password: <input type=\"password\" name=\"password\"></label>\n    <input value=\"Go\" type=\"submit\">\n  </form>\n";
        $this->register_var('content', $html);
        return;
      }
    }
    $icount = $this->$album->imagecount;
    if ($_POST['imageno'] && is_numeric($_POST['imageno'])) {
      if ($_POST['imageno'] <= $icount) {
        header('Location:' . BASE . $this->album . '/' . fakeUrl($this->$album->images[$_POST['imageno'] - 1]));
      }
    }
    $this->makeHeadLink('top', './', 'List of albums');
    $desc = $this->$album->description;
    $howmany = $icount > 1 ? "$icount pictures" : 'One picture';
	  $this->register_var('content', "<p class=\"imagecount\">$howmany</p>\n");
    if ($desc) {
      if (strlen($desc) > 350) $c = ' class="columnar"';
      $this->register_var('content', "  <p$c>$desc</p>\n");
    }
    if (is_numeric($fish[1]) || empty($fish[1])) $this->thumbView((int)$fish[1]);
    else $this->singleImageView($fish[1]);
    $this->gen($fish[1]);
  }

  public function thumbView($page) {
    $this->makeHeadLink('up', './', 'List of albums');
    $this->register_var('header', '<a href="./" title="Front page">' . $this->title . '</a> &raquo; ' . $this->{$this->album}->title);
    $this->options = $GLOBALS['options'];
    $ppp = $_POST['perpage'];
    $spp = $_SESSION['perpage'];
    $scpp = $_SESSION['customperpage'];
    $this->oldtoshow = $this->toshow = $spp ? ($spp === 'custom' && $scpp ? $scpp : $spp) : DEFAULTTHUMBS;
    if ($ppp && in_array($ppp, $this->options)) {
      if ($ppp === 'custom') {
        $pcpp = (int)$_POST['customperpage'];
        if (!in_array($pcpp, $this->options) && $pcpp > 0) {
          $_SESSION['perpage'] = $ppp;
          $this->toshow = $_SESSION['customperpage'] = $pcpp;
        }
        elseif ($pcpp > 0) {
          $this->toshow = $_SESSION['perpage'] = $pcpp;
          unset($_SESSION['customperpage']);
        }
      }
      else $this->toshow = $_SESSION['perpage'] = (int)$ppp;
    }
    if ($this->toshow < 1) $this->toshow = DEFAULTTHUMBS;
    $this->pages = (int)ceil($this->{$this->album}->imagecount / $this->toshow);
    $page = min(max($page, 1), $this->pages);
    $this->startmark = $this->oldtoshow * ($page - 1);
    $this->currentpage = (int)ceil($this->startmark / $this->toshow) + 1;
    $this->startmark = $this->toshow * ($this->currentpage - 1);
    $this->endmark = min($this->{$this->album}->imagecount, $this->startmark + $this->toshow);
    $this->options();
    if ($this->currentpage > 1) {
      $this->makePageNavLink('prev', $this->currentpage-1);
      $this->makeHeadLink('first', $this->album . '/1/', 'First page of thumbs');
      $this->makeHeadLink('prev', $this->album . '/' . $this->currentpage-1 . '/', 'Page '. ($this->currentpage-1));
    }
    if ($this->currentpage < $this->pages) {
      $this->makePageNavLink('next', $this->currentpage+1, $this->pages);
      $this->makeHeadLink('next', $this->album . '/' . $this->currentpage+1 . '/', 'Page '. ($this->currentpage+1));
      $this->makeHeadLink('last', $this->album . '/' . $this->pages . '/', 'Last page of thumbs');
    }
    $buff = '  <ul id="thumbarray">' . "\n";
    for ($i = $this->startmark; $i < $this->endmark ; $i++) {
      $image = $this->{$this->album}->images[$i];
 	    $imgsrc = $this->album . '/thumbs/' . strip_ext($image) . '.png';
      if (!is_file($imgsrc) && !createThumb($this->album, $image)) continue;
      $buff .= "    <li>    \n      <a href=\"" . $this->album . '/' . fakeUrl($image) . '"';
      $caption = $this->{$this->album}->captions[$image];
      $title = strip_tags($caption);
      $alt = truncate($title);
      $caption = truncate($caption);
      $size = @getimagesize($imgsrc);
      $buff .= ' class="thickbox" title="' . $title . '">
        <span><img src="' . $imgsrc . "\" alt=\"$alt\" $size[3]></span>
        <span class=\"caption\">$caption</span>\n";
      $datetime = getExif($this->album . "/$image", true);
      if ($datetime) $buff .= "      <span class=\"exif\">Taken $datetime</span>\n";
      $buff .= "      </a>    \n";
      $buff .= "    </li>    \n";
    }
    $this->register_var('content', $buff . '  </ul>' . "\n");
  }

  public function options() {
    $buff = '  <div id="bar">' . "\n";
    $imagecount = $this->{$this->album}->imagecount;
    if ($this->pages > 1) {
      $buff .= "    <span><strong>&nbsp;</strong>Page</span>\n    <div>\n      <ol";
      if ($this->pages > 9) $buff .= ' class="doubledigits"';
      $buff .= ">\n";
      for ($i = 1; $i <= $this->pages; $i++) {
        $c = $i === $this->currentpage ? ' class="current"' : '';
        $buff .= "        <li$c><a href=\"{$this->album}/$i/\">$i</a></li>\n";
      }
      $buff .= "      </ol>\n    </div>\n";
      $info = $this->startmark + 1 === $imagecount ? "<strong>the last lonely image</strong>" : (strval($this->toshow) === "1" ? "image <strong>" . ($this->starmark + 1) . "</strong>" : "images <strong>" . ($this->startmark + 1) . "</strong> to <strong>{$this->endmark}</strong>");
      $buff .= "    <span>of <strong>{$this->pages}</strong> showing $info</span>\n";
    }
    else {
      $buff .= '    <span>';
      if ($imagecount === 1) $buff .= 'The one and only image in this album';
      else $buff .= "All <strong>$imagecount</strong> images displayed";
      $buff .= "</span>\n";
    }
    $buff .= '    <form method="post" action="' . "{$this->album}/{$this->currentpage}/\">
      <fieldset>
        <legend>Settings</legend>\n";
    $buff .= '        <label for="perpage">Thumbs per page:</label>
        <select name="perpage" id="perpage"';
    if ($_SESSION['perpage'] === 'custom') $buff .= ' class="custom"';
    $buff .= '>' . "\n";
    foreach ($this->options as $o) {
      if ($o === 'custom') continue;
      $buff .= "          <option value=\"$o\"";
      $perpage = in_array($this->toshow, $this->options) ? $this->toshow : 'custom';
      $buff .= (string)$o === (string)$perpage ? ' selected="selected">' : '>';
      $buff .= $o;
      $buff .= "</option>\n";
    }
    $buff .= '        </select>' . "\n";
    if ((string)$perpage === 'custom') $buff .= '        <input type="text" maxlength="3" value="'.$_SESSION['customperpage'].'" name="customperpage">' . "\n";
    $buff .= '        <input type="image" src="img/right.png" alt="Go">
      </fieldset>
    </form>
  </div>' . "\n";
  $this->register_var('content', $buff);
  }

  public function makePageNavLink($dir, $index, $pages = false) {
    if (!$pages) {
      $anchortitle = $index > 1 ? 'Previous' : 'First';
      $anchortitle .= " {$this->toshow} images";
    }
    else {
      if ($index === $pages) {
        $dregs = $this->{$this->album}->imagecount - ($this->toshow * $index + 1);
        $anchortitle = $dregs > 1 ? "Last $dregs images" : "Last page, last image";
      }
      else $anchortitle = "Next {$this->toshow} images";
    }
    if ($index > 9) $nd = ' doubledigits';
    $buff = '  <div class="pagination ' . $dir . $nd . '">
    <a href="' . $this->album . '/' . $index . '/" title="' . $anchortitle . '">' . "\n";
    while ($s++ < 2) {
      if ($s === 2) $dir = 'page';
      $buff .= "      <span>";
      foreach (str_split($dir) as $letter) $buff .= "<span>$letter</span>";
      $buff .= "</span>\n";
    }
    $this->register_var('content', $buff . "    </a>\n    <a href=\"{$this->album}/$index/\">$index</a>\n  </div>\n");
  }

  public function singleImageView($image) {
    $images = $this->{$this->album}->images;
    $captions = $this->{$this->album}->captions;
    $imagecount = $this->{$this->album}->imagecount;
    $albumname = $this->{$this->album}->name;
    $this->makeHeadLink('up', $albumname . '/', $this->{$this->album}->title);
    $this->register_var('header', '<a href="./" title="Front page">' . $this->title . '</a> &raquo; <a href="' . $albumname . '/">' . $this->{$this->album}->title . '</a>');
    $current = $image ? (int)array_search(realUrl($image), $images) : 0;
    $buff = "  <div id=\"view\">\n";
    $buff .= "  <form action=\"{$_SERVER['REQUEST_URI']}/\" method=\"post\">\n    <fieldset>\n      <legend>Browse by position</legend>\n      <label>Go to # <input type=\"text\" name=\"imageno\"> / $imagecount</label>\n      <input type=\"image\" src=\"img/right.png\" alt=\"Go\">    </fieldset>\n  </form>\n";
    $buff .= "    <p>\n";
    if ($current > 0) {
      $this->makeHeadLink('first', $albumname . '/' . fakeUrl($images[0]), ampquot(strip_tags($captions[$images[0]])));
      $this->makeHeadLink('prev', $albumname . '/' . fakeUrl($images[$current-1]), ampquot(strip_tags($captions[$images[$current-1]])));
      $buff .= '      <a href="' . $this->album . '/' . fakeUrl($images[$current-1]) . '" title="' . strip_tags($captions[$images[$current-1]]) . "\">&laquo; Prev</a>\n";
    }
    $buff .= "      Image " . ($current + 1) . " of $imagecount\n";
    if ($current < $imagecount - 1) {
      $this->makeHeadLink('next', $this->album . '/' . fakeUrl($images[$current+1]), ampquot(strip_tags($captions[$images[$current+1]])));
      $this->makeHeadLink('last', $this->album . '/' . fakeUrl($images[$imagecount-1]), ampquot(strip_tags($captions[$images[$imagecount-1]])));
      $buff .= '      <a href="' . $this->album . '/' . fakeUrl($images[$current+1]) . '" title="' . strip_tags($captions[$images[$current+1]]) . "\">Next &raquo;</a>\n";
    }
    $buff .= "    </p>\n";
    $size = getimagesize($this->album . '/' . $images[$current]);
    $buff .= '    <img src="' . $this->album . '/' . $images[$current] . '" alt="' . strip_tags($captions[$images[$current]]) . '" ' . $size[3] . '>' . "\n";
    if (EXIF === true) {
      $exifdata = getExif($this->album . '/' . $images[$current], false);
      if ($exifdata) {
        $buff .= '    <div class="exif">' . "\n" .
                 '      <h4>EXIF data</h4>' . "\n" .
                 "      <dl>\n";
        foreach ($exifdata as $label => $value) {
          $buff .= "        <dt>$label:</dt>\n" .
                   "        <dd>$value</dd>\n";
        }
        $buff .= "      </dl>\n" .
                 "    </div>\n";
      }
    }
    $buff .= '    <p class="caption">' . $captions[$images[$current]] . '</p>
    <div class="thumbs">
      <ul>' . "\n";
    for ($i = max($current-2, 0), $j = min($current+3, $imagecount); $i < $j; $i++) {
      $image = $images[$i];
      $imgname = strip_ext($image);
      $imagehref = fakeUrl($image);
      $actclass = $i === $current ? ' class="active"' : null;
      $title = strip_tags($captions[$image]);
      $buff .= "        <li$actclass>
          <a href=\"" . $this->album . "/$imagehref\" title=\"$title\"><img src=\"" . $this->album . "/thumbs/$imgname.png\" alt=\"" . truncate($title) . "\"></a>
          <span>".($i+1)."</span>
        </li>\n";
    }
    $this->register_var('content', $buff . "      </ul>\n    </div>\n  </div>\n");
    $this->addBodyClass($_SESSION['topbit']);
  }

  public function randomImage($album) {
    if (!$album || !$this->$album) {
      $album = $this->albumlist;
      shuffle($album);
      $album = $album[0];
    }
    $images = $this->$album->images;
    shuffle($images);
    $thumb = $album . '/thumbs/' . strip_ext($images[0]) . '.png';
    return array("$album/{$images[0]}", $thumb, $this->$album->captions[$images[0]], $album, $this->$album->title, $images[0]);
  }

  public function titleSort($a, $b) {
    return $this->$a->title > $this->$b->title ? 1 : -1;
  }

  public function gen() {
    if (!$this->album) return;
    if ($this->currentpage && $this->currentpage !== $_SESSION['oldcurrentpage']) {
      $_SESSION['oldcurrentpage'] = $this->currentpage;
      $this->addHeadCSS("#bar div:hover ol {\n  top:-".(($this->currentpage - 1) * 1.3)."em;\n}");
    }
    if (filemtime('settings.php') > SETTINGSFILEMTIME + 1) {
      $buffer .= "ul#thumbarray li a span {\n  width:".(TMAXWIDTH)."px;\n  height:".TMAXHEIGHT."px;\n  line-height:".TMAXHEIGHT."px;\n}\n";
      $buffer .= "ul#thumbarray li a span.caption {\n  width:".(TMAXWIDTH + 24)."px;\n}\n";
      $buffer .= "#view .thumbs ul li a {\n  height:".(TMAXHEIGHT + 30)."px;\n  line-height:".(TMAXHEIGHT + 30)."px;\n}\n";
      $settings = file_get_contents('settings.php');
      $settings = preg_replace("/define\('SETTINGSFILEMTIME', \d+/", "define('SETTINGSFILEMTIME', " . time(), $settings);
      file_put_contents('settings.php', $settings);
    }
    if (!empty($buffer)) {
      $css = file_get_contents('shampoo.css');
      file_put_contents('shampoo.css' , substr($css, 0, strpos($css, '/* GENERATED STUFF */', filesize('shampoo.css') - 300)) . "/* GENERATED STUFF */\n" . $buffer);
      $this->register_var('cssfilemtime', '?' . time());
    }
  }

  public function addHeadCSS($css) {
    $curcss = $this->cache['headCSS'];
    if ($curcss) {
      $curcss = str_replace('<style type=\"text/css\">', '', $curcss);
      $curcss = str_replace('</style>', '', $curcss);
      $curcss = "\n  " . trim($curcss);
    }
    $css = str_replace("\n", "\n    ", $css);
    $curcss = "  <style type=\"text/css\">$curcss\n    $css\n  </style>\n";
    $this->register_var('headCSS', $curcss);
  }

  public function addBodyClass($class) {
    if (!$class) return;
    $cur = trim($this->cache['bodyclass'], '"');
    if (!$cur) $cur = ' class="' . $class . '"';
    else $cur .= " $class\"";
    $this->register_var('bodyclass', $cur, true);
  }

  public function makeHeadLink($rel, $href, $title) {
    $this->register_var('links', "  <link rel=\"$rel\" href=\"$href\" title=\"$title\">\n");
  }

  public function register_var($name, $value, $overwrite = false) {
    if ($overwrite) $this->cache[$name] = $value;
    else $this->cache[$name] .= $value;
  }

  public function output() {
    $template = file_get_contents('shampoo.inc') or exit('<br><b>Script stopped</b>: Check that the template file exists (default name is shampoo.inc) and that it is in the right directory (the same one as index.php)');
    $r = preg_match_all('/{(\w+)}/', $template, $matches);
    foreach ($matches[1] as $match) {
      $template = str_replace("{{$match}}", rtrim($this->cache[$match]), $template);
    }
    $template = preg_replace("/\n\s*\n/m", "\n", $template);
    echo utf8_encode($template);
  }
}

/* FUNCTIONS */

  function makePrettyTitle($title) {
    $title = preg_split('/[\s+\-_]+/', trim(htmlspecialchars($title, ENT_COMPAT, 'UTF-8')));
    foreach ($title as $k => $t) {
      $title[$k] = ucfirst($t);
    }
    return implode(' ', $title);
  }

  function ampquot($str) {
    return str_replace(array('&', '"'), array('&amp;', '&quot;'), $str);
  }

  function dateSort($a, $b) {
    return filemtime($a) < filemtime($b) ? 1 : -1;
  }

  function truncate($string) {
    if (strlen($string) > 70) return array_shift(explode("\n", wordwrap($string, 70))) . '...';
    return $string;
  }

  function isValidImage($image) {
    if (strrchr($image, '.') === '.txt') return false;
    $a = @getimagesize($image);
    if (($a[2] > 0 && $a[2] < 4) || strpos($image, 'bmp') > 0) return true;
  }

  function parseLine($line) {
    $line = utf8_decode(ltrim($line, "\xef\xbb\xbf")); // BOM must be removed, otherwise first line gets skipped
    if (strpos($line, "//") === 0) return false;
    return array_map('trim', explode("|", $line));
  }

  function realUrl($url) {
    return substr_replace($url, '.', strrpos($url, '_'), 1);
  }

  function fakeUrl($url) {
    return substr_replace($url, '_', strrpos($url, '.'), 1);
  }

  function strip_ext($str) {
    return substr($str, 0, strrpos($str, '.'));
  }

  function createThumb($album, $img) {
    $imgname = strip_ext($img);
    if (!is_dir("$album/thumbs")) {
      mkdir("$album/thumbs");
    }
    if (strpos($img, ' ') > -1) {
      $oldimg = $img;
      $img = str_replace(' ', '_', trim($img));
      $res = rename("$album/$oldimg", "$album/$img");
      if ($res !== true) $img = $oldimg;
    }
    $img = "$album/$img";
    list($width, $height, $type) = @getimagesize($img);
    if ($width === false) return log_error("$img isn't a valid image or it doesn't exist");
    if (TMAXWIDTH < $width && $width >= $height) {
      $thumbwidth = TMAXWIDTH;
      $thumbheight = ($thumbwidth / $width) * $height;
    }
    elseif (TMAXHEIGHT < $height && $height >= $width) {
      $thumbheight = TMAXHEIGHT;
      $thumbwidth = ($thumbheight /$height) * $width;
    }
    else {
      $thumbheight = $height;
      $thumbwidth = $width;
    }
    $imgbuffer = imagecreatetruecolor($thumbwidth, $thumbheight);
    switch($type) {
      case 1: $image = imagecreatefromgif($img); break;
      case 2: $image = imagecreatefromjpeg($img); break;
      case 3: $image = imagecreatefrompng($img); break;
      case 6: $image = imagecreatefrombmp($img); break;
      case 15: $image = imagecreatefromwbmp($img); break;
      default: return log_error("Tried to create thumbnail from $img: not a valid image");
    }
    if (!$image) return log_error("Image creation from $img failed for an unknown reason. Probably not a valid image.");
    else {
      imagecopyresampled($imgbuffer, $image, 0, 0, 0, 0, $thumbwidth, $thumbheight, $width, $height);
      $output = imagepng($imgbuffer, "$album/thumbs/$imgname.png", 9);
      imagedestroy($imgbuffer);
      return $output;
    }
  }

  function getExif($image, $onlydatetime) {
    $ex = @exif_read_data($image, 0);
    if ($ex === false) return false;
    if ($ex['DateTimeOriginal']) {
      list($date, $time) = explode(' ', $ex['DateTimeOriginal']);
      $datetime = date("j M Y", strtotime(str_replace(":", "/", $date))) . ', ' . substr($time, 0, 5);
      if (!$onlydatetime) $exifdata['Taken'] = $datetime;
    }
    if ($onlydatetime) return $datetime;
    if ($ex['Width']) $exifdata['Width'] = $ex['Width'];
    if ($ex['Height']) $exifdata['Height'] = $ex['Height'];
    if ($ex['Make'] || $ex['Model']) {
      if (strpos($ex['Model'], $ex['Make']) === 0) $exifdata['Camera'] = $ex['Model'];
      else {
        if ($ex['Make']) $exifdata['Make'] = $ex['Make'];
        if ($ex['Model']) $exifdata['Model'] = $ex['Model'];
      }
    }
    if ($ex['ExposureTime']) {
      $z = explode('/', $ex['ExposureTime']);
      if ($z[0] / $z[1] < 1) $exifdata['Exposure Length'] =  sprintf('1/%d sec.', $z[1] / $z[0]);
      else $exifdata['Exposure Length'] = sprintf('%d sec.', $z[0] / $z[1]);
    }
    if ($ex['FocalLength']) {
      $z = explode('/', $ex['FocalLength']);
      $exifdata['Focal Length'] = sprintf('%.1f mm', $z[0] / $z[1]);
    }
    if ($ex['COMPUTED']['ApertureFNumber'] || $ex['ApertureFNumber'] || $ex['FNumber']) {
      if ($ex['COMPUTED']['ApertureFNumber']) $exifdata['Aperture'] = $ex['COMPUTED']['ApertureFNumber'];
      else {
        $z = $ex['FNumber'] || $ex['ApertureFNumber'];
        $z = explode('/', $z);
        $exifdata['Aperture'] = sprintf('f/%.01f', pow(2, $z[0] / $z[1] / 2));
      }
    }
    if ($ex['ISOSpeedRatings']) {
      $exifdata['ISO Speed'] = $ex['ISOSpeedRatings'];
    }
    if ($ex['Flash']) {
      switch($ex['Flash']) {
        case 0x0000:
        case 0x0010:
        case 0x0018:
        case 0x0020:
        case 0x0058: $exifdata['Flash'] = 'Not fired'; break;
        default: $exifdata['Flash'] = 'Fired';
      }
    }
    return count($exifdata) > 0 ? $exifdata : false;
  }

  function imagecreatefrombmp($filename) { // Written by D H Kold (dhkold.com)
    if (!$handle = fopen($filename, "rb")) return false; //Open file in binary mode
    //1 : Load file headers
    $file = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($handle, 14));
    if ($file['file_type'] != 19778) return false;

    //2 : Load BMP headers
    $bmp = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
                  '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
                  '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($handle, 40));
    $bmp['colors'] = pow(2, $bmp['bits_per_pixel']);
    if ($bmp['size_bitmap'] == 0) $bmp['size_bitmap'] = $file['file_size'] - $file['bitmap_offset'];
    $bmp['bytes_per_pixel'] = $bmp['bits_per_pixel']/8;
    $bmp['bytes_per_pixel2'] = ceil($bmp['bytes_per_pixel']);
    $bmp['decal'] = ($bmp['width']*$bmp['bytes_per_pixel'] / 4);
    $bmp['decal'] -= floor($bmp['width'] * $bmp['bytes_per_pixel'] / 4);
    $bmp['decal'] = 4 - (4 * $bmp['decal']);
    if ($bmp['decal'] == 4) $bmp['decal'] = 0;

    //3 : Load palette colours
    if ($bmp['colors'] < 16777216) {
     $palette = unpack('V' . $bmp['colors'], fread($handle, $bmp['colors']*4));
    }

    //4 : Image creation
    $img = fread($handle, $bmp['size_bitmap']);
    $vide = chr(0);

    $res = imagecreatetruecolor($bmp['width'], $bmp['height']);
    $p = 0;
    $y = $bmp['height'] - 1;
    while ($y >= 0) {
     $x = 0;
     while ($x < $bmp['width']) {
      if ($bmp['bits_per_pixel'] == 24)
         $color = unpack("V", substr($img, $p, 3) . $vide);
      elseif ($bmp['bits_per_pixel'] == 16) {
         $color = unpack("n", substr($img, $p, 2));
         $color[1] = $palette[$color[1]+1];
      }
      elseif ($bmp['bits_per_pixel'] == 8) {
         $color = unpack("n", $vide . substr($img, $p, 1));
         $color[1] = $palette[$color[1] + 1];
      }
      elseif ($bmp['bits_per_pixel'] == 4) {
         $color = unpack("n", $vide . substr($img, floor($p), 1));
         if (($p * 2) % 2 == 0) $color[1] = ($color[1] >> 4) ;
         else $color[1] = ($color[1] & 0x0F);
         $color[1] = $palette[$color[1] + 1];
      }
      elseif ($bmp['bits_per_pixel'] == 1) {
         $color = unpack("n", $vide . substr($img, floor($p), 1));
         if     (($p*8)%8 == 0) $color[1] =  $color[1]        >>7;
         elseif (($p*8)%8 == 1) $color[1] = ($color[1] & 0x40)>>6;
         elseif (($p*8)%8 == 2) $color[1] = ($color[1] & 0x20)>>5;
         elseif (($p*8)%8 == 3) $color[1] = ($color[1] & 0x10)>>4;
         elseif (($p*8)%8 == 4) $color[1] = ($color[1] & 0x8)>>3;
         elseif (($p*8)%8 == 5) $color[1] = ($color[1] & 0x4)>>2;
         elseif (($p*8)%8 == 6) $color[1] = ($color[1] & 0x2)>>1;
         elseif (($p*8)%8 == 7) $color[1] = ($color[1] & 0x1);
         $color[1] = $palette[$color[1]+1];
      }
      else return false;
      imagesetpixel($res, $x, $y, $color[1]);
      $x++;
      $p += $bmp['bytes_per_pixel'];
     }
     $y--;
     $p += $bmp['decal'];
    }
    fclose($handle);
    return $res;
  }

  function log_error($error) {
    file_put_contents('errors.log', $error . "\r\n", FILE_APPEND);
    return false;
  }
?>
Return current item: Shampoo