#!/usr/bin/perl -w
# Version 1.0
# Author: miles@tenhand.com
# Home/Docs/Licensing http://www.tenhand.com/blosxthis

# USAGE: |./blosxthis.pl password  /path/to/blogdir [/path/to/countfile] 
# If there are two arguments, a plaintext password is used. 
# If there are three, we will verify that the user's password is 
# in the chain of hashes starting with the first hash of the password
# and ending with the number stored in the countfile.
# What the program does:
# Read STDIN/mail message  looking for one of the following commands:
# "blog-this: Password" (add a new blog entry) 
# "kill-this: Password blog.txt (delete blog.txt entry)
# "edit-this: Password blog.txt (replace blog.txt entry with this email)
# 
# This program goes to silly lengths to exit in a way that 
# doesn't expose system information and is always right for the 
# mailer software. If you think this is a bug, change the BAIL 
# entries to something more verbose

use Digest::MD5 qw(md5 md5_hex);

$top=0;
($secret,$path,$countfile) = @ARGV;
if ( $countfile) { # find out our current count
    open (C,"$countfile") or &BAIL;
    <C>=~/^(\d+)/;    
    $top+=$1;
    close C;
}

my $x=0;
while (<STDIN>) {
    if (/^(\S+)\-*this: (\S+)(.*)/i ) {
	$ba=$1; $pass=$2; $rest=$3; 
	last;
    }
    ($x > 30) ? &BAIL : $x++;
}

 ($pass) ? &checkpw() : &BAIL;

for ($ba) {
   if ( /blog/i || /post/i ) {
	&postblog ? &GOOD : &TEMP; 
    } else { # we are changing an existing file
	#files with only safe characters in filename
	 unless ($rest =~/^\s+([a-zA-Z0-9\-\_]+)\s*/) { &BAIL} ; 
	 $file= $path . $1 . "\.txt";
	 unless ( -f $file ) { &BAIL; }
    }
   if  ( /del/i || /kill/i )   {
	unlink ($file) ? &GOOD :  &BAIL ;
    }
   if  ( /edit/i || /update/i || /mod/i )    {
	@mtime= stat($file);
	$mt=$mtime[9];
	&postblog($file) and utime($mt,$mt,$file) ; #move mtime back 
	&GOOD; # posting is good enough
    }
   &BAIL; # no command found
}

sub checkpw() {
    for ($x=1; $x <= $top; $x++) { 
	$secret=md5_hex($secret);
	if ( $secret =~ /^$pass/) { 
	    open (C,">  $countfile ") or &BAIL;
	    print C $x-- . "\n";
	    close C;
	    return (1);
	}
    }
 unless ($countfile) { if  ( $pass eq $secret ) { return(1); } }
 &BAIL ;
}

sub postblog() {
    ($file) = @_; my $x=0;
    unless ( $file ) { $file = "$path/" . time() . "\.txt"; }
    open ( BLOG, ">$file") or &TEMP;
    while (<STDIN>) {
	if ( ! /\S/) { next; }  #  Use HTML if you need blank lines
	if ( /^------=_NextPart/ ) { last; } # drop HTML mail duplication
	# s/\<script /\<\&gt\>script /; # kill off cross site scripting?
	($x<300) ? $x++ : &BAIL; # this is a blog, not moby dick.
	print BLOG $_; 
    }
    close BLOG;
    ( -z $file)   ? unlink "$file" :  chmod 0644, $file ;  
    return 1;
}

#### The exit codes must match your mail server
sub BAIL { # clearly bounce mail. 
    exit (100); }#qmail is 100, sendmail is 1,
sub TEMP { &BAIL; } #usually better to bail
#    exit (111);} # qmail is 111, sendmail is 75
sub GOOD {  exit (0); } # mail accepted


