#!/usr/bin/perl


push @INC, '/home/greg/web/www.estren.net/htdocs/VisualMoo/';

# VisualMoo, Picture Poster
# Author: Greg Estren
# Date: September 27, 2003
#
###############################################

use CGI;



#################################################  
#
# Initialization
#
############

$basedir = '/home/greg/web/www.estren.net/htdocs/VisualMoo';

$commentdir = $basedir . '/comments';
$postdir = $basedir . '/posts';
$templatedir = $basedir . '/templates';
$htmldir = $basedir . '/html';
$picdir = $basedir . '/pics';

$header1 = '/home/greg/web/www.estren.net/htdocs/templates/header_head.html';
$header2 = '/home/greg/web/www.estren.net/htdocs/templates/header_body.html';
$footer = '/home/greg/web/www.estren.net/htdocs/templates/footer.html';
$posttemplate = $templatedir . '/happyPost.html';
$previewtemplate = $templatedir . '/previewPost.html';
$commentstemplate = $templatedir . '/commentsTemplate.shtml';


# web-style directory reference (for links)
$picURLdir = '/VisualMoo/pics';

$commentfile = 'comments.shtml';   # name of file containing comments for each post


$sendmail = '/bin/sendmail -t greg@estren.net';

#################################################  
#
# Retrieve all parameters (and make sure they're all valid)
#
############

$rawinput = new CGI;

print "Content-type: text/html\n\n";



# Here's how we figure it out: if there's a GET value passed of "newpost=true" append
# to the script URL, then we're not in the "First time loaded".  If that GET isn't there,
# We just assume NO incoming input and print out the initial form.
$firstload = 1;
if ($rawinput->url_param('newpost')) {     # url_param = query string parameters (GET)
    $submitter = $rawinput->param('name');
    $title = $rawinput->param('title');
    $location = $rawinput->param('location');
    $comment = $rawinput->param('comment');

    $picname = $rawinput->param('picdata');
    $thumbname = $rawinput->param('thumbdata');

    $firstload = 0;
}

else {
    $firstload = 1;
    $previewmode = 1;
}





$previewmode = 0;  # always in raw-submit mode currently
$submitted = 0;
if ($rawinput->param('preview')) {$previewmode = 1; $submitted = 1;}
if ($rawinput->param('submit')) {$submitted = 1;}







# safety-check (strip weird-ass characters out)
$submitter =~ s/[^a-zA-Z0-9\_\-\+\=\.\,\?\"\'\:\;\/\!\@\#\$\%\^\&\*\(\)\[\]\{\}\s]//g;
$title =~ s/[^a-zA-Z0-9\_\-\+\=\.\,\?\"\'\:\;\/\!\@\#\$\%\^\&\*\(\)\[\]\{\}\s]//g;
$location =~ s/[^a-zA-Z0-9\_\-\+\=\.\,\?\"\'\:\;\/\!\@\#\$\%\^\&\*\(\)\[\]\{\}\s]//g;
$comment =~ s/[^a-zA-Z0-9\_\-\+\=\.\,\?\"\'\:\;\/\!\@\#\$\%\^\&\*\(\)\[\]\{\}\s]//g;









if ($previewmode) {
    $outtemplate = $previewtemplate;
}
elsif (!$submitter && !$picname) {
    $outtemplate = $previewtemplate;
}
else {
    $outtemplate = $posttemplate;
}







#################################################  
#
# Save the data for the new post
#
############


# Get EST time zone (local seems to be 2 hours before EST?)
@l = localtime(time() + 60*60*2);


$year = $l[5] + 1900;
$month = $l[4] + 1;
if ($month < 10) {$month = "0$month";}

$day = $l[3];
if ($day < 10) {$day = "0$day";}

$hour = $l[2];
if ($hour < 10) {$hour = "0$hour";}

$minute = $l[1];
if ($minute < 10) {$minute = "0$minute";}

$second = $l[0];
if ($second < 10) {$second = "0$second";}

$date = $year . "-" . $month . "-" . $day . "_" .
    $hour . ":" . $minute . ":" . $second;



# Save the picture: get the filename (minus directory),
# prefix with current title, save to file

if ($picname) {


    if (($picname =~ /\.jpe?g/i) || ($picname =~ /\.gif/i)) {
	$serverpicname = $picname;
	$serverpicname =~ s/^.*[\\\/]//;
	$serverpicname =~ s[^a-zA-Z0-9\_\-\.]//g;
	$serverpicname = $date . "_" . $serverpicname;
	
	if (open OUTFILE, ">$picdir/$serverpicname") {
	    while ($bytesread=read($picname,$buffer,1024)) {
		print OUTFILE $buffer;
	    }
	    close OUTFILE;
	}
	else {
	    $errormode = 1;
	    $errormessage = "I can't seem to write the file onto the web server.";
	}
	# else error-opening-outfile
	
	$picname = $serverpicname;
    }
    else {
	$errormode = 1;
	$errormessage = "Your picture doesn't seem to be a JPEG or GIF file.  I can't deal " .
	    " with other types of image files.";	
    }
}


# Save the thumb: get the filename (minus directory),
# prefix with current title, save to file

if ($thumbname) {

    if (($thumbname =~ /\.jpe?g/i) || ($thumbname =~ /\.gif/i)) {
	$serverthumbname = $picname;
	$serverthumbname =~ s/^.*[\\\/]//;
	$serverthumbname =~ s[^a-zA-Z0-9\_\-\.]//g;
	$serverthumbname = $date . "_" . "thumb_" . $serverthumbname;
	
	if (open OUTFILE, ">$picdir/$serverthumbname") {
	    while ($bytesread=read($thumbname,$buffer,1024)) {
		print OUTFILE $buffer;
	    }
	    close OUTFILE;
	}
	# else error opening outfile
	else {
	    print "can not open to $picdir/$serverthumbname<br>\n";
	}
	
	$thumbname = $serverthumbname;
    }
    else {
	$errormode = 1;
	$errormessage = "Your thumbnail doesn't seem to be a JPEG or GIF file.  I can't deal " .
	    " with other types of image files.";	
    }
}





# Try to determine dimensions for pics
if ($picname && !$errormode) {
    if ($picname =~ /\.jpe?g/i) {
	($picx, $picy) = jpegsize("$picdir/$picname");
    }
    elsif ($picname =~ /\.gif/i) {
	($picx, $picy) = gifsize("$picdir/$picname");

    }
    $picsize = "$picx x $picy";
}


if ($thumbname && !$errormode) {

    if ($thumbname =~ /\.jpe?g/i) {
	($thumbx, $thumby) = jpegsize("$picdir/$thumbname");
    }
    elsif ($thumbname =~ /\.gif/i) {
	($thumbx, $thumby) = gifsize("$picdir/$thumbname");

    }
    $thumbsize = "$thumbx x $thumby";
}






# see if pic name was already specified in CGI form
if (!$picname && !$errormode) {
    $picname = $rawinput->param('previewpicname');
    $picsize = $rawinput->param('picsize');

    if ($picname && ($picname !~ /\.jpe?g/i) && ($picname !~ /\.gif/i)) {
	$errormode = 1;
	$errormessage = "Your picture doesn't seem to be a JPEG or GIF file.  I can't deal " .
	    " with other types of image files.";	
    }


}
if (!$thumbname && !$errormode) {
    $thumbname = $rawinput->param('previewthumbname');
    $thumbsize = $rawinput->param('thumbsize');

    if ($thumbname && ($thumbname !~ /\.jpe?g/i) && ($thumbname !~ /\.gif/i)) {
	$errormode = 1;
	$errormessage = "Your thumbnail doesn't seem to be a JPEG or GIF file.  I can't deal " .
	    " with other types of image files.";	
    }
}



# Save the post entry (if in save mode).  Otherwise
# do nothing (and go to previewmode)

if (!$previewmode && !$errormode) {   # if postmode (not previewmode)

    if ($submitter && $picname && $picsize) {
	$name = $submitter;
	$name =~ s/\s/_/g;
	
	$postfile = $date . "_" . $name . ".post";

	if (open OUTFILE, ">$postdir/$postfile") {
	    print OUTFILE "Submitter: $submitter\n" if ($submitter);
	    print OUTFILE "Title: $title\n" if ($title);
	    print OUTFILE "Location: $location\n" if ($location);
	    print OUTFILE "Comment: $comment\n" if ($comment);
	    print OUTFILE "Picture: $picname\n" if ($picname);
	    print OUTFILE "Thumb: $thumbname\n" if ($thumbname);
	    print OUTFILE "Picsize: $picsize\n" if ($picsize);
	    print OUTFILE "Thumbsize: $thumbsize\n" if ($thumbsize);
	    
	    close OUTFILE;
	}
	# else could-not-write-file-error
    }
}





#################################################  
#
# IF IN PREVIEW MODE: show post preview
#
############

elsif ($previewmode) {
}







#################################################  
#
# IF IN POST MODE: update HTML page 
#
############

if (!$previewmode && $submitter && $picname && $picsize && !$errormode) {

    require 'generatePosts.pl';

    
# Add a directory and basic HTML file for comments
    if ($picname) {
	my $whichpic = $picname;

	$whichpic =~ s/\.(.*)$//;
	mkdir "$commentdir/$whichpic", 0755;
	
# Copy over the default (zero) comments page
	open INFILE, $commentstemplate;
	@data = <INFILE>;
	close INFILE;
	

	
	open OUTFILE, ">$commentdir/$whichpic/$commentfile";
	$incomment = 0;
	foreach (@data) {
	    s/\#WHICHPOST\#?/$whichpic/gi;
	    
	    if (/^(.*)\#STARTCOMMENT\#?(.*)$/i) {
		$_ = "$1$2";
		$incomment = 1;
	    }
	    elsif (/^(.*)\#ENDCOMMENT\#?(.*)$/i) {
		$_ = "$1$2";
		$incomment = 0;
	    }
	    elsif ($incomment == 1) {   # we don't want to print individual comment HTML just yet 
		$_ = "";
	    }
	    
	    
	    print OUTFILE $_;
	}
	
	close OUTFILE;
    }
    
}    
    
    
    
    


#################################################  
#
# Display output to the user
#
############

if (!$firstload && $submitted && (!$submitter || !$picname) && !$errormode) {
    $errormode = 1;

    if (!$picname) {
	$errormessage = "You haven't included any picture.";
    }
    elsif (!$submitter) {
	$errormessage = "You didn't give yourself a name.";
    }
}

    



# See if our pic is too big (whatever is displayed on the main
# post page), if so enter error mode

if ($thumbname && !$errormode) {
    $thumbsize =~ /^(\d+).*?(\d+)$/;
    $thumbx = $1;
    $thumby = $2;

    if (($thumbx > 640) || ($thumby > 480)) {
	$errormode = 1;
	$errormessage = "Your thumbnail picture is too big (bigger than 640x480).";
    }

    if ($thumbx < 10 || $thumby < 10) {
	$errormode = 1;
	$errormessage = "Your thumbnail picture is too small (smaller than 10x10).";
    }
}
elsif (!$errormode)  {
    $picsize =~ /^(\d+).*?(\d+)$/;
    $picx = $1;
    $picy = $2;

    if (($picx > 640) || ($picy > 480)) {
	$errormode = 1;
	$errormessage = "Your picture is too big (bigger than 640x480).  Maybe you want " .
	    "to use a thumbnail?";
    }

    if ($picx < 10 || $picy < 10) {
	$errormode = 1;
	$errormessage = "Your picture is too small (smaller than 10x10).";
    }
}







$picurl = $picURLdir . '/' . URLEncode($picname);
$thumburl = $picURLdir . '/' . URLEncode($thumbname);

open INFILE, $header1;
while (<INFILE>) {print;}
close INFILE;

open INFILE, $header2;
while (<INFILE>) {print;}
close INFILE;


# What's the URL link to the image that will display in the main post?
$imglink = $picname;
if ($thumbname) {$imglink = $thumbname;}
$imglink = $picURLdir . '/' .  $imglink;

$realimglink = $picname;
$realimglink = $picURLdir . '/' .  $realimglink;



$picsize =~ /^(\d+).*?(\d+)/;
$imgx = $1;
$imgy = $2;
$realimgx = $1 + 50;   # the plus is used since we use these dimensions for opening a new HTML
$realimgy = $2 + 90;   # window and we need a bit of buffer space beyond the image size

if ($thumbname) {
    $thumbsize =~ /^(\d+).*?(\d+)/;
    $imgx = $1;
    $imgy = $2;
}








# Figure out descriptive day information

$dayofweek = zeller($day, $month, $year);   # get day of week from date
$dayofweek = (Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday)[$dayofweek];

$month = ("",Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$month];

my $amorpm = "AM";
if ($hour >= 12) {
    $amorpm = "PM";
    $hour -= 12 if ($hour >= 13);
}

$time = "$month $day, $year  -- ${hour}:${minute} $amorpm";







open INFILE, $outtemplate;
while (<INFILE>) {
    s/#submitter#?/$submitter/ig;
    s/#title#?/$title/ig;
    s/#comment#?/$comment/ig;
    s/#location#?/$location/ig;
    s/#picname#?/$picname/ig;
    s/#thumbname#?/$thumbname/ig;
    
    s/#picurl#?/$picurl/i;
    s/#thumburl#?/$thumburl/i;

    s/\#picsize\#?/$picsize/i;
    s/\#thumbsize\#?/$thumbsize/i;


    s/\#imglink\#?/$imglink/i;
    s/\#imgx\#?/$imgx/i;
    s/\#imgy\#?/$imgy/i;

    s/\#DAYOFWEEK\#?/$dayofweek/gi;
    s/\#\MONTH#?/$month/gi;
    s/\#\DAYOFMONTH#?/$day/gi;
    s/\#\YEAR#?/$year/gi;


    if (/\#PREVIEWMODE[\#\:]?/i) {
	if (!$previewmode || $errormode) {$_ = "";}
	else {

	    s/\#PREVIEWMODE[\#\:]?//i;	    
	}
    }

    s/\#REALIMGLINK\#?/$realimglink/i;
    s/\#realimgx\#?/$realimgx/i;
    s/\#realimgy\#?/$realimgy/i;

    if (/\#IFTHUMB[\#\:]?/i) {
	if (!$thumbname || $errormode) {$_ = "";}
	else {
	    s/\#IFTHUMB[\#\:]?//i;	    
	}
    }

    
    s/\#ERRORMESSAGE\#?/$errormessage/gi;

    if (/\#ERRORMODE[\#\:]?/i) {
	if ($errormode && !$firstload) {
	    s/\#ERRORMODE[\#\:]?//i;
	}
	else {$_ = "";}
    }


    if (/\#FIRSTLOADMODE[\#\:]?/i) {
	if ($firstload) {
	    s/\#FIRSTLOADMODE[\#\:]?//i;
	}
	else {$_ = "";}
    }

    


    print;
}
close INFILE;


open INFILE, $footer;
while (<INFILE>) {print;}
close INFILE;



if (($submitted == 1) && ($previewmode == 0)) {
    open MAIL, "|$sendmail";
    print MAIL "From: \"VisualMoo Photoblog\" <www@estren.net> \n";
    print MAIL "To: \"Greg Estren\" <greg\@estren.net>\n";
    print MAIL "Subject: new picture posted!!!!\n\n";
    print MAIL "\nThere's a new photoblog picture from $name:\n\n";
    close MAIL;
}






#################################################
#
# Subroutines (the useful kind)
#
#############

sub gifsize {
# return a string of height and width tags for a gif. this code "adapted"
# from: http://rajiv.org/programming/gifsize.txt

    my ($GIF) = @_; my ($w, $w2, $h, $h2, $gifwidth, $gifsize, $type,$width,
			$height) = () ;

    open INFILE, "<$GIF"; read INFILE, $type, 3; seek INFILE, 6, 0; read
	INFILE, $w, 1; read INFILE, $w2, 1; read INFILE, $h, 1; read INFILE, $h2,
	1; close INFILE;

    $width = ord ($w) + ord ($w2) * 256; $height = ord ($h) + ord ($h2) * 256;
    return ($width,$height); 
 }




sub jpegsize { 

    my ($JPEG) = @_;
    my ($done) = 0;
    my ($size) = "";
    my($c1,$c2,$ch,$s,$c,$d,$junk,$length);
    
    open INFILE,"<$JPEG"; 
    read(INFILE, $c1, 1); 
    read(INFILE, $c2, 1); 
    if( !((ord($c1) == 0xFF) && (ord($c2) == 0xD8))){
	#print "This is not a JPEG!"; 
	$done=1; 
    } 

    my $outermarker = 0;

    while (ord($ch) != 0xDA && !$done && ($outermarker < 1000)) {
	$outermarker++;

# Find next marker (JPEG markers begin with 0xFF) This can hang the program!!
	my $innermarker = 0;
	while ((ord($ch) != 0xFF) && ($innermarker < 10000)) {
	    read(INFILE, $ch, 1); 
	    $innermarker++;
	}
	
	$innermarker = 0;
# JPEG markers can be padded with unlimited 0xFF's
	while ((ord($ch) == 0xFF) && ($innermarker < 10000)) {
	    read(INFILE, $ch, 1); 
	    $innermarker++;
	}
	
# Now, $ch contains the value of the marker.
	if ((ord($ch) >= 0xC0) && (ord($ch) <= 0xC3)) {
	    read (INFILE, $junk, 3);
	    read(INFILE, $s, 4); ($a,$b,$c,$d)=unpack("C"x4,$s); 
	    $x = $c<<8|$d;
	    $y = $a<<8|$b;
	    $done = 1;
#	    $size=join("", '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 (INFILE, $s, 2); 
	    ($c1, $c2) = unpack("C"x2,$s);
	    $length = $c1<<8|$c2; 

	    if(($length < 2) ){ 
#print "Erroneous JPEG marker length"; 
		$done=1; 
	    } 
	    else {
		read(INFILE, $junk, $length-2);
	    } 
	} 
    } 

    return ($x, $y)
}






sub URLEncode {
    my $str=  shift @_;

    $str =~s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;

    return $str;
}




sub zeller {
    local($day,$month,$year) = @_;
    local($k, $m, $y, $c, $d, $z);

    $k = $day;
    $m = $month - 2; # first month of year used to be March
    $y = $year;

    if ($m <= 0) {
        $m += 12; # Jan & Feb are months 11 and 12
        $y -= 1; # of the previous year
    }

    $c = int($y / 100); # century
    $d = $y % 100;  # year of century

    $z = (int(2.6 * $m - 0.2) + $k + $d + int($d/4) + int($c/4) - 2*$c) % 7;

    return $z;
}
