#!/usr/bin/perl -w
#
# next.cgi v0.1.2       --crb3 01jun03/06jun03/13apr07
#
# display a sorted list of same-type graphics,
# using GET method so images can be bookmarked.
#
# copyright (c) 2003 C. R. Bryan III
# crb3@stormbringer.org
#
# v0.1          --crb3 06jun03  first working version
# v0.1.1        --crb3 19jun03  filter out angles
# v0.1.2        --crb3 13Apr07  fix userdirs, improve arrays
#
# This program is free software.  You can redistribute it and/or modify
# it under the terms of the GNU General Public License
#
#
$isarg=1;
if(defined($ENV{'QUERY_STRING'})){              # GET params
  $query=$ENV{'QUERY_STRING'};
  $isarg=0 if length($query)<2;
}else{
  $isarg=0;
}

$showall=0;
if($isarg){                             # textbook slice 'n' dice stuff rather
  foreach $cmd (split('&',$query)) {    #  than pull in a heaping helping
    ($key,$arg)=split('=',$cmd);        #  of CPAN.
    $arg =~ tr/+/ /;
    $arg =~ s/\%([a-fA-F0-9]{2})/pack("C",hex($1))/eg;
    if(exists($CGI{$key})){
      $CGI{$key} .= ",$arg";
    }else{
      $CGI{$key} = $arg;
    }
  }
  undef($query);
  $now = $CGI{'x'};             # that arg could be hand-typed. gotta de-louse it.
  $now =~ s/\.+\//\//g;         # squish out dots followed by slashes
  $now =~ s/\/{2,}/\//g;        # reduce toothpick piles, and any other
  $now =~ s/[<>;?*:%]+//g;      # shell chars that might cause path troubles
  $now =~ s/\0//g;              # when tacked onto docroot ...or obstreperous nulls
  $ddir = $now;                 # split it into a data-dir and a now-imagefile
  substr($ddir,rindex($ddir,'/')+1)="";
  substr($now,0,rindex($now,'/')+1)="";
}else{
  $now='';
}
$showall = (0+$CGI{showall}==1 ? 10if exists $CGI{showall};
$action=$ENV{'SCRIPT_NAME'};    # how this script got called

$htdir=$ENV{'HTTP_REFERER'};            # ignore all this if there are args
                                        #  otherwise we need it to find the
$htdir =~ s/^http\:\/\///i;             #  directory with the pix in it
substr($htdir,0,index($htdir,'/'))="";  # whack off hostname
substr($htdir,rindex($htdir,'/')+1)=""# whack off filename

$webdir=($isarg ? $ddir : $htdir);
if( ($ptx=index($webdir,'~'))>-1){      # special handling for users'
  $pty=index($webdir,'/',$ptx);         # home directories. assumes that
  substr($webdir,$pty,0)='/public_html';
  substr($webdir,$ptx,1)='home/';       # ~user is equivalent to docroot of
}else{                                  # /home/user/public_html.
  $webdir=$ENV{'DOCUMENT_ROOT'}.'/';
  $webdir .= ($isarg ? $ddir : $htdir);
}
$ddir=$htdir unless $isarg;

chdir $webdir;

(@gfn)=(sort ((<*.gif>),(<*.GIF>)));
$gfv=$#gfn;                             # THESE ARE CASE SENSITIVE
(@jfn)=(sort ((<*.jpg>),(<*.jpeg>),(<*.JPG>)));
$jfv=$#jfn;                             # not 'jpeg'
(@pfn)=(sort ((<*.png>),(<*.PNG>)));
$pfv=$#pfn;

unless($showall){
  if($gfv > $jfv){              # which type has the most files
    $fn = 'g'$fnv=$gfv;               #  in this directory?
  }else{
    $fn = 'j'$fnv=$jfv;
  }
  if($pfv > $fnv){
    $fn = 'p'$fnv=$pfv;
  }
  (@fn)=(@gfnif $fn eq 'g';   # low-memory systems might need this
  (@fn)=(@jfnif $fn eq 'j';   #  to point a reference instead of
  (@fn)=(@pfnif $fn eq 'p';   #  copying an array
}else{
  push(@fn,(sort (@gfn,@jfn,@pfn)));
  $fnv=$#fn;
}
undef(@gfn);                    # let go of array memory
undef(@jfn);
undef(@pfn);

$hbar = ($isarg ? "&nbsp;" : "<hr>" );  # 'isarg' indicator for debugging.

if($isarg){                     # find which file we should show next.
  $state=0;
  if($now eq "" or $now eq $fn[$fnv]){  # last-page handling
    $prior = $fn[$fnv-1];
    $next = $fn[0];
  }else{
    foreach $fnow (@fn){
      if($state==0){
        unless($fnow eq $now){
          $prior=$fnow;         # at state-change, it's the one sent last time
          next;
        }
        $state++;
      }elsif($state==1){        # ...and the one to put in the 'next' link.
        $next=$fnow;
        $state++;
      }else{                    # explicit, in case mods need more states
        last;
      }
    }
    $prior=$fn[$fnvunless defined $prior;     # rerun-firstpage touchup
  }
}else{                          # entry (first) page's 'prior' link wraps
  $prior = $fn[$fnv];           #  around to last one. others increment
  $now = $fn[0];                #  from there. this is for when we just
  $next=$fn[1];                 #  got in from the redirect, with no args.
}
$next = $fn[0unless defined $next;    # at last page? wrap around to start

$title=$action;
substr($title,0,rindex($title,'/')+1)="";
$title .= "$now";             # something explicit for the <title>

#
# the internal HTML page could be supplanted by a template fetch-and-fill,
#  but this looks good enough for the basic job. you might want less of a
#  border around the picture.
# links top-and-bottom are handy when you're browsing scanned manga pages.
#

print <<EOT;
Content-Type: text/html

<html>
<head>
  <title>$title</title>
</head>
<body bgcolor="#909090">
<center>
<h3>$now</h3>
<table align="center">
<tr><td align="right">
<a href="$action?x=$ddir$prior">prior</a>
</td><td width="25%">
$hbar
</td><td align="left">
<a href="$action?x=$ddir$next">next</a>
</td></tr>
<tr><td colspan="3" align="center">
<img src="$ddir$now" vspace="5" border="4" align="center">
</td></tr>
<tr><td align="right">
<a href="$action?x=$ddir$prior">prior</a>
</td><td width="25%">
$hbar
</td><td align="left">
<a href="$action?x=$ddir$next">next</a>
</td></tr>
</table>
</center>
</html>
EOT

Grab the
tarball
here
 
Syntax highlighting using Syntax::Highlight::Engine::Kate