#!/usr/bin/perl 
##################
# copyright and GPL (http://www.gnu.org/licenses/gpl.html)
# Barry Hughes <bazza@bazza.com>
# photo galleries that are a little more automatic and sensible
# than just filename lists, or running a script that takes 3 years to
# generate everything, this only generates the served images when
# they're viewed. if you're not running your web server with suexec, you'll
# need to create the dirs yourself, and make sure the user the web server is
# running as will need write access to "images" and "thumbnails"
# Additions: weird ratio support, checking of URL specified sizes, and
# switching width to height if image is portrait rather than landscape
# thanks to the Loony <eaganj@bazza.com>, updated next/previous links
# idea semi stolen from zgal (http://zgal.sf.net)
# This version will also browse directories if you want

use Cwd;
use Date::Manip;
use Image::Info qw(image_info);
use Image::Magick;

# Some config stuffs
$thumbwidth = "100";
@imagewidths = qw/640 800 1024 1600/;
$imagesperrow;
$imagesperrow = 4;
$defaultwidth = "640";
$base_dir = "/var/www/bazza/photos";
$relative_path = "";
# Overlay image, this is a png, and is mostly transparent
$wmark = "watermark.png";

# Logo for bottom of pages (from webroot)
$logo = "/bazza.com.jpg";

# Dir icon when dir browsing
$dirimage = "/dir.png";

# Directories
$images = "images";
$comments = "comments";
$thumbs = "thumbnails";
$originals = "originals";
@subdirs = qw/images comments thumbnails/;

if($ENV{HTTP_USER_AGENT} =~ /^Mozilla\/4/) {
  if($ENV{HTTP_USER_AGENT} =~ /MSIE/) { 
    $style = "style=\"border:1px solid #000000\"";
  } else {
    $style = " ";
  }
} else {
  $style = "style=\"border:1px solid #000000\"";
}


my $type;
if ($ENV{PATH_INFO} =~ /^\/+/) { &error; }
unless($ENV{PATH_INFO}) {
  if(-d "$originals") { $type = "thumbindex"; } else { $type = "dirlist"; }
} elsif($ENV{PATH_INFO} =~ /^\/thumb/) {
  $type = "thumb";
} elsif($ENV{PATH_INFO} =~ /^\/show/) {
  $type = "show";
} elsif($ENV{PATH_INFO} =~ /^\/view/) {
  $type = "view";
} else {
  $type = "thumbindex";
}

if($type =~ /thumbindex/) {
  my $checkdir = "$ENV{REQUEST_URI}/";
  $checkdir =~ s/\/\//\//g;
  $checkdir =~ s/$ENV{SCRIPT_NAME}\///;
  unless(-d "$checkdir$originals") { 
    $type = "dirlist"; 
    chdir($checkdir) or $type = "error";
  } else {
    chdir($checkdir);
  }
}

if($type =~ /dirlist/) {
  $title = $ENV{REQUEST_URI};
  $title =~ s/$0//;
  $title =~ s/\/\//\//g;
} elsif($type =~ /thumbindex/) {
  $title = $ENV{REQUEST_URI};
  $title =~ s/$ENV{SCRIPT_NAME}\///;
} elsif($type =~ /thumb/) {
  thumb();
  die;
} elsif($type =~ /view/) {
  view();
  die;
}


# Header
my $output = <<END;
Content-Type: text/html

<html>
<head>
<style type="text/css">
 A:link { COLOR: #0080C0; }
 A:visited { COLOR: red; }
 A:hover { COLOR: #000099; }
 A:active { COLOR: red; }
 A { text-decoration: none; }
</style>
<title>$title</title></head>
<script language=javascript src="/.js/awstats_misc_tracker.js"></script>
<body bgcolor="#FFFFFF">
END

if($type =~ /dirlist/) {
  $output .= dirlist();
} elsif($type =~ /thumbindex/) {
  $output .= thumbindex();
} elsif($type =~ /show/) {
  $output .= show();
} else {
  $output .= error();
}
  

# Foot
if($logo) {
  $output .= <<END;
  <p>&nbsp;<p>
  <p>
  <center><a href="http://bazza.com/"><img src="$logo" border="0"></a></center>
END
}
$output .= <<END;
</body>
</html>
END


print $output;


sub dirlist {
  my @updir = split("/",$ENV{REQUEST_URI});
  my $foo = pop(@updir);
  my $updir = join("/",@updir);
  my $pwd = cwd();
  #unless($pwd =~ /$ENV{DOCUMENT_ROOT}/) { die;}
  my $dirlist = <<END;
<font face="Arial, Helvetica" size="-1">
<a href="$updir">../</a>&nbsp;&nbsp;<a href="$updir">Previous Dir</a>
<center><p>$title<p></center>
<table align="center" cellpadding="10" $style bgcolor="#ffffff">

END
  foreach(sort <*>) {
    next if($_ =~ /\./);
    push(@dirs,$_);
  }
  $dirnumber = 1;
  foreach(@dirs) {
    if($dirnumber eq 1) { $output .= "<tr align=\"center\">\n"; }
    $dir = $_;
    $dirlist .= <<END;
  <td width="200" align= "center" valign="top">
    <font face="Arial, Helvetica" size="-1">
END
    if($ENV{PATH_INFO}) {
      $dirlist .= "<a href=\"$ENV{SCRIPT_NAME}$ENV{PATH_INFO}/$_\"><img src=\"$dirimage\" border=\"0\"></a>\n";
      my $name = $_;
      $name =~ s/_/ /g;
      $dirlist .= "<p><a href=\"$ENV{SCRIPT_NAME}$ENV{PATH_INFO}/$_\">$name</a><br>\n";
    } else {
      $dirlist .= "<a href=\"$ENV{SCRIPT_NAME}/$_\"><img src=\"$dirimage\" border=\"0\"></a>\n";
      my $name = $_;
      $name =~ s/_/ /g;
      $dirlist .= "<p><a href=\"$ENV{SCRIPT_NAME}/$_\">$name</a><br>\n";
    }
    $dirlist .= "</font></td>\n";
    if($dirnumber eq 4) { 
      $dirlist .= "</tr>\n";
      $dirnumber = 1;
    } else {
      $dirnumber++;
    }
  }
$dirlist .= <<END;
  </tr>
  </table>
END
  return $dirlist;
}

sub error {
  my $link = $ENV{SCRIPT_NAME};
  my $error = <<END;
  <font face="Arial, Helvetica">The directory $title does not exist, please click <a href="$link">here</a> to return to the main dir
  </font>
END
  return $error;
}

sub thumbindex {
  @dirs = qw/images comments thumbnails/;
  foreach(@dirs) {
    if(-e $_) { next; }
    mkdir($_);
  }
  open(TITLE, "title");
  my $title = <TITLE>;
  my @updir = split("/",$ENV{REQUEST_URI});
  my $foo = pop(@updir);
  my $updir = join("/", @updir);
  my $thumbindex = <<END;
  <font face="Arial, Helvetica" size="-1"><a href="$updir">../</a>&nbsp;&nbsp;<a href="$updir">Previous Dir</a><p>
  <center><p>$title<p></center>
  <table align="center" cellpadding="10" $style bgcolor="#eeeeee">
END
  chdir("$originals");
  foreach(<*>) {
    next unless($_ =~ /jpg/);
    push(@images,$_);
  }
  $imagenumber = 1;
  foreach(@images) {
    my $cmt = $_;
    $cmt =~ s/.jpg//;
    if(-e "../$comments/$cmt.txt") {
      open(COMMENT, "../$comments/$cmt.txt");
      $comment = <COMMENT>;
    }
    if($imagenumber eq 1) { $thumbindex .= "<tr align=\"center\">\n"; }
    $image = $_;
    $image =~ s/\.jpg//;
    if(-e "../$thumbs/$image.jpg") {
      my $path =  $ENV{REQUEST_URI};
      $path =~ s/index.cgi//;
      $path =~ s/\/\//\//g;
      $thumb = "$path/$thumbs/$image.jpg";
    } else {
      $thumb = "$ENV{SCRIPT_NAME}/thumb$ENV{PATH_INFO}/$_";
    }
    $thumbindex .= <<END;
  <td width="200" valign="top">
    <font face="Arial, Helvetica" size="-1">
    <a href="$ENV{SCRIPT_NAME}/show$ENV{PATH_INFO}/$image-$defaultwidth.jpg"><img src="$thumb" border="0" $style></a>
    <p>$_<br>
END
    foreach(@imagewidths) {
      my $width = $_;
      my $ratio = &get_ratio;
      my $height;# = int($width * $ratio);
      if ($ratio > 1) {
          $height = $width;
          $width = int($height / $ratio);
      } else {
          $height = int($width * $ratio);
      }
      $thumbindex .= <<END;
  <a href="$ENV{SCRIPT_NAME}/show$ENV{PATH_INFO}/$image-$_.jpg">$width x $height</a><br>
END
    }
    if($comment) { $thumbindex .= "$comment\n"; }
    undef $comment;
    close(COMMENT);
    $thumbindex .= "</font></td>\n";
    if($imagenumber eq 4) { 
      $thumbindex .= "</tr>\n";
      $imagenumber = 1;
    } else {
      $imagenumber++;
    }
  }
  $thumbindex .= <<END;
  </tr>
  </table>
END
  return $thumbindex;
}

sub get_ratio {
  my $path = $ENV{PATH_TRANSLATED};
  $path =~ s/$ENV{DOCUMENT_ROOT}//;
  $path =~ s/\/thumb//;
  $path =~ s/\/view//;
  $path =~ s/\/show//;
  $path =~ s/$image\.jpg//;
  $path =~ s/$image-$width\.jpg//;
  $path =~ s/\/\//\//;
  $path .= "/";
  my $info = image_info("$base_dir$path$originals/$image.jpg");
  $output .= "$info->{error}\n";
#  print "$info->{error}\n";
  my $height = $info->{height};
  my $width = $info->{width};
#  print "originals: $height x $width\n";
  my $ratio = $height / $width;
  return($ratio);
}


sub test {

  print "Content-Type: text/plain\n\n";

  print "$< $>\n\n";
  foreach(sort keys %ENV) {
    print "$_ = $ENV{$_}\n";
  }
}

sub thumb {
#  print "Content-Type: text/plain\n\n";
  my @image = split("/", $ENV{PATH_INFO});
  $image = $image[$#image];
  $image =~ s/\.jpg//;
  $thumbx = $thumbwidth;
  my $ratio = &get_ratio;
  if ($ratio > 1) {
      $thumby = $thumbx;
      $thumbx = int($thumby / $ratio);
  } else {
      $thumby = int($thumbx * $ratio);
  }

  print "Content-Type: image/jpeg\n\n";
  $tmb = Image::Magick->new;
  my $path = $ENV{PATH_TRANSLATED};
  $path =~ s/$ENV{DOCUMENT_ROOT}//;
  $path =~ s/\/thumb//;
  $path =~ s/$image.jpg//;
  $path =~ s/\/\//\//;
  $tmb->Read("$base_dir$path$originals/$image.jpg");
  $tmb->Resize(width=>$thumbx,height=>$thumby);
  $tmb->Write("$base_dir$path$thumbs/$image.jpg");
  binmode STDOUT;
  $tmb->Write('jpg:-');
}

sub view {
  my @image = split("/", $ENV{PATH_INFO});
  $image = $image[$#image];
  $image =~ s/\.jpg//;
  ($image, $width) = split("-", $image);
  my $ratio = &get_ratio;
  if ($ratio > 1) {
      $height = $width;
      $width = int($height / $ratio);
  } else {
      $height = int($width * $ratio);
  }
  my $path = $ENV{PATH_TRANSLATED};
  $path =~ s/$ENV{DOCUMENT_ROOT}//;
  $path =~ s/\/view//;
  $path =~ s/$image-$width.jpg//;
  $path =~ s/$image-$height.jpg//;
  $path =~ s/\/\//\//;
  print "Content-Type: image/jpeg\n\n";
  $img = Image::Magick->new;
  $img->Read("$base_dir$path$originals/$image.jpg");
  $watermark = Image::Magick->new;
  unless(-e "$base_dir$path/nomark") {
    $watermark->Read($wmark);
    $img->Composite(compose=>"Atop", image=>$watermark, gravity=>"SouthEast");
  }
  $img->Resize(width=>"$width",height=>"$height");
  if ($height / $width > 1) {
      $img->Write("$base_dir$path$images/$image-$height.jpg");
  } else {
      $img->Write("$base_dir$path$images/$image-$width.jpg");
  }
  binmode STDOUT;
  $img->Write('jpg:-');
}

sub show {
  my @image = split("/", $ENV{PATH_INFO});
  $image = $image[$#image];
  $image =~ s/\.jpg//;
  ($image, $width) = split("-", $image);
  foreach(@imagewidths) {
    if($width =~ /$_/) {
      $goodwidth = "1";
    }
  }
  my $index = $ENV{PATH_INFO};
  $index =~ s/\/show//;
  $index =~ s/\/$image-$width.jpg//g;
  $index = "$ENV{SCRIPT_NAME}$index";
  my $path = $ENV{PATH_INFO};
  $path =~ s/show\///;
  $path =~ s/$image-$width.jpg//g;
if(-e "$base_dir$path$images/$image-$width.jpg") {
  my $dir = $relative_path;
  if($goodwidth) {
    $view = "$dir$path$images/$image-$width.jpg";
  } else {
    $view = "$dir$path$images/$image-$defaultwidth.jpg";
  }
} else {
  if($goodwidth) {
    $view = "$ENV{SCRIPT_NAME}/view$path$image-$width.jpg";
  } else {
    $view = "$ENV{SCRIPT_NAME}/view$path$image-$defaultwidth.jpg";
  }
}

  my $show .= <<END;
  <font face="Arial, Helvetica" size="-1"><a href="$index">Back to Index</a>
  <center>
  <table cellpadding="0" cellspacing="0" border=0>
    <tr><td></td>
    <td bgcolor="#FFFFFF" colspan="3" width="$width" align="centre">
      <center>
      <img src="$view" $style>
      </center>
    </td>
    <td></td></tr>

END
chdir("$base_dir$path$originals");
foreach(<*>) {
  my $orig = $_;
  $orig =~ s/.jpg//;
  push (@images, $orig);
}

for my $i (0..$#images) {
  if($images[$i] =~ /$image/) {
    if($i) {
      ($prev, $next) = ($images[$i-1], $images[$i+1]);
    } else {
      ($prev, $next) = (undef,$images[$i+1]);
    }

  }
}

if($prev) {
  $show .= "  <tr><td bgcolor=\"#eeeeee\" width=\"100\" valign=\"center\">\n";
  $show .= "  <center><a href=\"$ENV{SCRIPT_NAME}/show$path$prev-$width.jpg\"><img src=\"$dir$path$thumbs/$prev.jpg\" $style></a><br>\n";
  $show .= "  <a href=\"$ENV{SCRIPT_NAME}/show$path$prev-$width.jpg\"><font face=\"Arial, Helvetica\" size=\"-1\">Previous</a></center>\n";
  $show .= "  </td>\n";
} else {
  $show .= "  <td bgcolor=\"#eeeeee\" width=\"100\"><font color=\"#eeeeee\">No previous image</font></td>\n";
} 

  $show .= <<END;
  <td bgcolor="#eeeeee" align="center" width="150"><font face="Arial, helvetica" size="-1">View At:<p>
END
  foreach(@imagewidths) {
    my $width = $_;
    my $ratio = &get_ratio;
    my $height;# = int($width * $ratio);
    if ($ratio > 1) {
        $height = $width;
        $width = int($height / $ratio);
    } else {
        $height = int($width * $ratio);
    }
    $show .= "  <a href=\"$ENV{SCRIPT_NAME}/show$path$image-$_.jpg\">$width x $height</a><br>\n";
  }
  $show .= "  </td>";

$info = image_info("$base_dir$path$originals/$image.jpg");
$datetime = $info->{DateTimeDigitized};
$datetime =~ s/:/-/;
$datetime =~ s/:/-/;
$datetime =~ ParseDate($datetime);
$takendate = UnixDate($datetime, "%a %b %e %H:%M:%S %Y");
$show .= <<END;
  <td bgcolor="#eeeeee" align="left" width="200">
  <br><font size="-1">Original Size:&nbsp;$info->{width}x$info->{height}</font>
  <br><font size="-1">Flash:&nbsp;$info->{Flash}</font>
  <br><font size="-1">Taken with:&nbsp;$info->{Model}</font>
  <br><font size="-1">ISO:&nbsp;$info->{ISOSpeedRatings}</font>
  <br><font size="-1">Shutter Speed:&nbsp;$info->{ExposureTime}</font>
END
  
# If you're not me, you probably don't want this hack, the date was generally
# wrong on my finepix, so we're just not going to show my ineptness :)
if($info->{Model} =~ /EOS/) {
($fstop1, $fstop2) = split ('/', $info->{FNumber});
$fstop = $fstop1 / $fstop2;
$show .= <<END;
  <br><font size="-1">Taken:&nbsp;$takendate</font>
  <br><font size="-1">F Stop:&nbsp;$fstop</font>
    
END
  $show .= "  </td>\n";
}
$show .= "<td bgcolor=\"#eeeeee\" valign=\"top\">\n";
  if(-e "$base_dir$path$comments/$image.txt") {
    $show .= "<font face=\"Arial, Helvetica\" size=\"-1\">";
    open(COMMENT, "$base_dir$path$comments/$image.txt");
  $show .= <COMMENT>;
  } else { $show .= "<font color=\"#eeeeee\">no comment</font>"; }
$show .= "</td>";

if($next) {
  $show .= "  <td bgcolor=\"#eeeeee\" width=\"100\" valign=\"center\">\n";
  $show .= "  <center><a href=\"$ENV{SCRIPT_NAME}/show$path$next-$width.jpg\"><img src=\"$dir$path$thumbs/$next.jpg\" $style></a><br>\n";
  $show .= "  <a href=\"$ENV{SCRIPT_NAME}/show$path$next-$width.jpg\"><font face=\"Arial, helvetica\" size=\"-1\">Next</a></center>\n";
  $show .= "  </td>\n";
} else {
  $show .= "  <td bgcolor=\"#eeeeee\" width=\"100\" valign=\"center\"><font color=\"#eeeeee\">no next image</font></td>\n";
}
$show .= <<END;
 </tr>
</table>
END
  return($show);
}



syntax highlighted by Code2HTML, v. 0.9.1