#!/usr/local/bin/perl # # AUTOKEEN LITE - v0.924 # # Brought to you by the fine people at Keenspot (http://www.keenspot.com) # # Autokeen Lite is a comic strip archive system, programmed by Darren Bleuel # (gav@nukees.com). It is fully public domain and open source. I ask that # if you make changes to this script, you not remove my name or Keenspot's # from these comment lines, and that you drop me a line about your changes, # if they are significant. # # # Installation of Autokeen Lite requires that your webhost allows cgi # scripts. Download this program to your cgi directory and configure # the "SETUP VARIABLES" below to correspond to your system. # # HAVE A SUPER KEEN DAY! # # Other info: # Please note that I learned perl programming from a reference manual, not a # programming manual, so some routines may seem less than perfectly efficient. # I don't know how compatible this code will be with operating systems other # than Linux or Unix. I'd appreciate feedback in this area. # # SETUP VARIABLES # --------------- # # The following is the absolute pathname to your account space where your # html files are installed. $path = "/home/nukees/public_html/"; # $webpath is the path relative to your home directory on your website. $url = "http://www.nukees.com/"; # This is the directory, relative to "$path", where your comics are stored, # if stored locally. $comicdir = "comics/"; # This is the directory, relative to "$url", from where this program will be # run. $cgidir = "cgi-bin/"; # This is the directory, relative to "$path", where your images are stored # for the "forward" and "backward" buttons, etc. (See README.txt for more) $imagedir = "images/"; # Here are some other options that can be customized if you really feel it's # necessary. See manual for further details. $dailytemplate = "dailytemplate.html"; $indextemplate = "indextemplate.html"; $storylinefile = "storylines.txt"; # This is the number of hours by which your system clock will be adjusted # if in a different time zone (Example: +3 will adjust from PST to EST). $timeoffset = 0; # START OF PROGRAM # ---------------- # # Don't change anything below this line unless you know what you're doing. #----------------------------------------------------------------------------- $programname = $0; $programname =~ s/.*(\/|\\)//; $path .= "/" if ($path !~ /(\/|\\)$/); $comicdir .= "/" if ($comicdir !~ /(\/|\\)$/); $cgidir .= "/" if ($cgidir !~ /(\/|\\)$/); $imagedir .= "/" if ($imagedir !~ /(\/|\\)$/); $url .= "/" if ($url !~ /(\/|\\)$/); # I'm sure there was a more elegant way to do the above, but what the hell # do I care? print "Content-type: text/html\r\n\r\n"; $timenow = time(); ($sec,$min,$hour,$day,$month,$year) = (localtime($timenow+(3600*$timeoffset)))[0,1,2,3,4,5]; $month = "0".$month if (++$month < 10); $day = "0".$day if ($day < 10); $year += 1900; $sec = "0".$sec if ($sec < 10); $min = "0".$min if ($min < 10); $truetoday = $year.$month.$day; %tags = ("***comic***" => "todays_comics", "***date***" => "echodate", "***year***" => "echoyear", "***month***" => "echomonth", "***day***" => "echoday", "***dayofweek***" => "echodayofweek", "***next***" => "nextday", "***previous***" => "prevday", "***first***" => "firstday", "***last***" => "lastday", "***storylines***" => "sldropdown"); @taglist = keys(%tags); $qs = $ENV{'QUERY_STRING'}; @qs = split(/&/,$qs); foreach $i (0..$#qs) { $qs[$i] =~ s/\+/ /g; $qs[$i] =~ s/%(..)/pack("c",hex($1))/ge; ($name, $value) = split(/=/,$qs[$i],2); $qs{$name} = $value; } $strip = $qs{"strip"}; $date = $qs{"date"}; $date = $qs if ($date eq "" && $strip eq ""); if (opendir(DIR, "$path$comicdir")) { @files = readdir(DIR); closedir DIR; } else { print "can't opendir $path$comicdir: $!"; exit; } @comics = sort {($a =~ /^\D*(\d+)/)[0] <=> ($b =~ /^\D*(\d+)/)[0] || ($a =~ /^\D*(\d+.*)\./)[0] cmp ($b =~ /^\D*(\d+.*)\./)[0] || $a cmp $b} @files; $ncom = $#comics; $j = 0; for ($i = 0; $i <= $ncom; $i++) { ($comicdates[$i-$j] = $comics[$i-$j]) =~ s/\D*(\d*)?.*/$1/; if ($comics[$i-$j] =~ /\d+.*\.(gif|jpg|html|GIF|JPG|HTML|htm|HTM|txt|TXT)$/ && $comicdates[$i-$j] <= $truetoday) { $comichash{$comicdates[$i-$j]} = $i-$j if ($comicdates[$i-$j] ne $lastdate); $lastdate = $comicdates[$i-$j]; } else { splice (@comics, $i-$j++, 1); } } splice (@comicdates, $#comicdates, 1) if ($comicdates[-1] > $truetoday); $today = $date; ($today = $strip) =~ s/\D*(\d+)?.*/$1/ if ($today eq ""); $today = $comicdates[$#comics] if ($today eq ""); $infile = "$path$dailytemplate"; $infile = "$path$indextemplate" if ($today eq $comicdates[$#comics]); parsetags($infile,"-"); sub parsetags { my $infile = $_[0]; my $outfile = $_[1]; if (open(FILE, $infile)) { my $page = ""; while () { my $line = $_; foreach $tag (@taglist) { if ($line =~ /\Q$tag\E/) { $subr = $tags{$tag}; $replace = &$subr; $line =~ s/\Q$tag\E/$replace/g; } } $page .= $line; } open(OUTFILE, ">$outfile") ? (print OUTFILE $page) : (print ("$outfile could not be opened for writing.\n")); close(OUTFILE); close(FILE); } else { print "$infile could not be opened for reading\n"; } } # The following subroutine, "dayofweek" can return three different values, # depending on the second arguement: # # 0: Normal operation. Returns the Day of Week (Sunday, Monday, etc). # 1: Returns the Day of Week as a numeral (Sun=0, Mon=1, etc). # 2: Returns the number of days since 1/1/1968 # # First arguement is the date, in YYYYMMDD format sub dayofweek { my $daytab = [[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]]; my @daynames = (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday); my $date = $_[0]; my $flag = $_[1]; my $year = substr($date,0,length($date)-4); my $month = substr($date,length($date)-4,2)-1; my $day = substr($date,length($date)-2,2); $day += $$daytab[leapyear($year)][$month] while (--$month>=0); $day += (365 + leapyear($year)) while (--$year>=1968); if ($flag == 0) { return $daynames[$day%7]; } elsif ($flag == 1) { return $day%7; } else { return $day; } } # Note: It has not been "offically" adopted that the year 4000 will not be a # leap year, as would be logical by our current leap year rules. However, I # expect that this rule will be adopted if civilization, calendars, and/or # this program still exist in the year 4000, and therefore I have made the # following routine Y4K compliant. sub leapyear { return ($_[0]%4 == 0 && $_[0]%100 !=0 || $_[0]%400 == 0 && $_[0]%4000 != 0) } sub days2date { my $daytab = [[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]]; my $day = $_[0]; my $year = 1968; my $month = 0; $day -= (365 + leapyear($year++)) while ($day-(365+leapyear($year))>0); $day -= $$daytab[leapyear($year)][$month++] while ($day-$$daytab[leapyear($year)][$month] > 0); $month++; $day = "0".$day if ($day < 10); $month = "0".$month if ($month < 10); return $year.$month.$day; } sub gifdim ($) { my $filename = $_[0]; open(GIF, $filename) || (warn "$filename not readable\n" && return undef, undef); my $buf = ''; my $n = read GIF, $buf, 10; close GIF; return (undef, undef) if $n < 10; my ($head, $width, $height) = unpack("A6vv", $buf); return (undef, undef) unless $head =~ /^GIF8[79]a/; return ($height,$width); } #----------------------------------------------------------------------------# # jpegsize : gets the width and height (in pixels) of a jpeg file # Andrew Tong, werdna@ugcs.caltech.edu February 14, 1995 # modified slightly by alex@ed.ac.uk, and again by gav@nuc.berkeley.edu sub jpegSize { my ($filename) = @_; my ($done) = 0; my ($height) = 0; my ($width) = 0; open(JPEG, $filename) || (warn "$filename not readable\n" && return undef, undef); read(JPEG, $c1, 1); read(JPEG, $c2, 1); if( !((ord($c1) == 0xFF) && (ord($c2) == 0xD8))){ print "This is not a JPEG!"; $done=1; } while (ord($ch) != 0xDA && !$done) { # Find next marker (JPEG markers begin with 0xFF) # This can hang the program!! while (ord($ch) != 0xFF) { read(JPEG, $ch, 1); } # JPEG markers can be padded with unlimited 0xFF's while (ord($ch) == 0xFF) { read(JPEG, $ch, 1); } # Now, $ch contains the value of the marker. if ((ord($ch) >= 0xC0) && (ord($ch) <= 0xC3)) { read (JPEG, $junk, 3); read(JPEG, $s, 4); ($a,$b,$c,$d)=unpack("C"x4,$s); $height = $a<<8|$b; $width = $c<<8|$d; $done=1; } else { # We **MUST** skip variables, since FF's within variable names are # NOT valid JPEG markers read (JPEG, $s, 2); ($c1, $c2) = unpack("C"x2,$s); $length = $c1<<8|$c2; if( ($length < 2) ){ print "Erroneous JPEG marker length"; $done=1; } else { read(JPEG, $junk, $length-2); } } } return ($height,$width); } #----------------------------------------------------------------------------# sub echocomic { my $text = ""; if (-f "$path$comicdir$comicfile") { if ($comicfile =~ /(gif|GIF)$/) { ($heightref, $widthref) = gifdim("$path$comicdir$comicfile"); $text .= "\"Today\'s "; } elsif ($comicfile =~ /(jpg|JPG)$/) { ($heightref, $widthref) = jpegSize("$path$comicdir$comicfile"); $text .= "\"Today\'s "; } elsif ($comicfile =~ /(html|HTML|txt|TXT|htm|HTM)$/) { if (!(open(HTMLFILE, "$path$comicdir$comicfile"))) { print "$path$comicdir$comicfile not readable."; exit; } while () { $text .= $_; } close(HTMLFILE); } return $text; } else { print "$path$comicdir$comicfile not readable.\n"; return ""; } } sub todays_comics { my $text = ""; my $next = ""; my $i = $comichash{$today}; local $comicfile = $comics[$i]; while ($comicdates[$i] eq $today && $i <= $#comics) { $text .= echocomic(); $comicfile = $comics[++$i]; } return $text; } sub showdaytag { my $file = $_[0]; my $alt = $_[1]; my $imagefile = "$file.gif"; (my $height, my $width) = gifdim("$path$imagedir$file.gif") if (-f "$path$imagedir$file.gif"); if (-f "$path$imagedir$file.jpg") { $imagefile = "$file.jpg"; ($height, $width) = jpegSize("$path$imagedir$file.jpg") if (-f "$path$imagedir$file.jpg"); } $height ? return qq~$alt~ : return qq~$alt~; } sub firstday { my $firstdate = $comicdates[0]; return "" if ($firstdate >= $today); local $link = "$url$cgidir$programname\?date=$firstdate"; return showdaytag("firstday","The First Comic"); } sub prevday { my $j=$#comics; do { $prevdate = $comicdates[$j--]; } until ($prevdate < $today || $j < 0); return "" if ($today <= $prevdate); local $link = "$url$cgidir$programname\?date=$prevdate"; return showdaytag("previousday","Previous Comic"); } sub nextday { my $j=0; do { $nextdate = $comicdates[$j++]; } until ($nextdate > $today || $j > $#comics); return "" if ($today >= $nextdate); # my $nextdate = $comicdates[$comichash[$today]+1]; local $link = "$url$cgidir$programname\?date=$nextdate"; return showdaytag("nextday","Next Comic"); } sub lastday { my $lastdate = $comicdates[$#comics]; return "" if ($lastdate <= $today); local $link = "$url$cgidir$programname\?date=$lastdate"; return showdaytag("lastday","Today\'s Comic"); } sub echodate { my $mo = echomonth(); my $yr = echoyear(); my $dy = echoday(); my $dw = dayofweek($today,0); return "$dw, $mo $dy, $yr"; } sub echomonth { my @monthnames = (January, February, March, April, May, June, July, August, September, October, November, December); return $monthnames[substr($today,length($today)-4,2)-1]; } sub echoyear { return substr($today,0,length($today)-4); } sub echoday { return substr($today,length($today)-2,2)+0; } sub echodayofweek { return dayofweek($today,0); } sub sldropdown { my $text = "$path$storylinefile"; if (open (DROPDOWN, "$path$storylinefile")) { $text = "
 
\n"; } return $text; }