#!/usr/bin/perl -T

#Postomatic is a script that will allow you to post blosxom entries from the web.             
#Author: Brett O'Connor - bretto AT blimpsgo90.com

#DISCLAIMER:                                      
#This software is offered to you for free without any technical support or 
#liability on the author's part.  Use at your own risk!  Also, you're going to 
#probably have to know a little about perl and your server setup to get this working.  
#No offense, but I am not available to help you out! Feel free to email any basic 
#setup questions but you are mostly on your own here, mkay?

#INSTALLATION:
#Configure the variables below and put this in a place where it is accesable from the
#web.  Make sure it is executable and also that it can write to your blosxom directory.

#REVISION HISTORY:
#0.3 - Readied for public release.

require CGI;
require IO::File;
use Fcntl;

#These are the variables you will want to configure:
$websiteName = "my blosxom"; #name of your website/weblog/blog/blosxom/whatever
$websiteUrl = "http://myhost.com/cgi-bin/blosxom.cgi"; #url to your blosxom.cgi
%logins = ( #login and then password for each user as key/value pair
    user => 'password',
    user2 => 'password2'
);
$dataDir = "/where/your/entries/are/kept"; #absolute path to entries
$fileExtension = "txt"; #just like $file_extension in your blosxom.cgi

#Ok, this stuff you probably won't need to change 
$versionNumber = "0.3";

#get paramaters
$query = CGI::new();
#check for login
if ($query->cookie('postomaticLogin')) {
    $login = $query->cookie('postomaticLogin');
    #determine current action
    if ($query->param('action')) {
        $action = $query->param('action');
    } else {
        $action = 'newEntry';#default for having a cookie
    }
} else {
    if ($query->param('action') eq 'checkLogin') {
        $action = 'checkLogin';
    } else {
        $action = 'newLogin';#default for not having a cookie
    }
}
#set cookie headers or check for login and print regular headers
if ($action eq 'checkLogin') {
    $loginAttempt = $query->param('login');
    $passwordAttempt = $query->param('password');
    $loginOk = 0;
    if (($loginAttempt ne '') && ($passwordAttempt ne '')) {
        if ($logins{$loginAttempt} eq $passwordAttempt) {
            $loginOk = 1;
        }
    }
    if ($loginOk eq 1) {
        $loginCookie = $query->cookie(
            -NAME=>'postomaticLogin',
            -VALUE=>$loginAttempt,
            -EXPIRES=>"+1d");
        print $query->header(-COOKIE => $loginCookie);
        $login = $loginAttempt;
        $action = 'newEntry';
    } else {
        printf("Content-type: text/html\n\n");
        $error = "Login incorrect. Hit your back button and try again.";
    }
} elsif ($action eq 'logout') {
    $logoutCookie = $query->cookie (
                -NAME=>'postomaticLogin',
                -VALUE=>'',
                -EXPIRES=>'-1d'
    );
    print $query->header(-COOKIE => $logoutCookie);
    $action = 'newLogin';
} else {
    printf("Content-type: text/html\n\n");
}
#start the body html
&print_html_top;
#print errors from top login stuff
if ($error) {
    print "<p class=\"error\">ERROR: ".$error."</p>";
    die;
}
#perform actions and create interfaces
if ($action eq 'newLogin') {
    &print_html_content('loginForm');
} elsif ($action eq 'newEntry') {
    @directories = get_directories($dataDir);
    if ($error) {
        print "<p class=\"error\">ERROR: ".$error."</p>";
        die;
    } else {
        &print_html_content('newEntry');
    }
} elsif ($action eq 'loadEntry') {

} elsif ($action eq 'editEntry') {

} elsif ($action eq 'previewEntry') {
    $fileName = $query->param('fileName');
    $fileIn = $query->param('fileIn');
    $title = $query->param('title');
    $text = $query->param('text');
    if ($fileName =~ m/\s+/) {
        $error = "Please don't have spaces in your file name.  Hit your back button to try again.";
    }
    if (($fileName eq '') || ($title eq '') || ($text eq '') || ($fileIn eq 'none-selected')) {
        $error = "All fields are required.  Hit your back button to try again.";
    }

    $fileName = $login.".".$fileName.".".$fileExtension;

    #if this is new make sure there isn't already a file by that name
    $postDir = $dataDir."/".$fileIn;
    opendir(DIR, $postDir) or $error = "Coudln't open ".$postDir.": $!";
    @files = readdir(DIR);
    foreach $file (@files) {
        if ($file eq $fileName) {
            $error = "An entry named ".$fileName." already exists in ".$postDir.".  Hit your back button to try again.";
        }
    }
    closedir(DIR);
    #convert the line breaks to <br /> tags if they asked for it
    if ($query->param('convertBreaks')) {
        $text =~ s/\r/<br \/>/gm;
    }
    $previewEntry = 1;
    if ($error) {
        print "<p class=\"error\">ERROR: ".$error."</p>";
        die;
    } else {
        &print_html_content('previewEntry');
    }
} elsif ($action eq 'postEntry') {
    #post the entry
    $fileName = $query->param('fileName');
    $fileIn = $query->param('fileIn');
    $title = $query->param('title');
    $text = $query->param('text');
    $posterName = $query->param('posterName');
    #assemble the full path to the file
    $completeFileRef = $dataDir.$fileIn."/".$fileName;

    $completeFileRef =~ /(.*)/;
    $completeFileRef = $1;

    #write the sucker
    $fh = IO::File->new($completeFileRef, O_WRONLY|O_TRUNC|O_CREAT) or $error = "Couldn't write to $completeFileRef: $!\n";
    if(!$error) {
        print $fh $title."\n";
        print $fh $text;
        $fh->close;
    }
    if ($error) {
        print "<p class=\"error\">ERROR: ".$error."</p>";
        die;
    } else {
        &print_html_content('postEntry');
    }
} elsif ($action eq 'deleteEntry') {

} elsif ($action eq 'createDirectory') {

}
#end of page
&print_html_bottom;
#action subroutines
#html subroutines
sub print_html_top
{
    print "<html><title>Post-O-Matic</title>
    <style type=\"text/css\"> 
    <!-- 
        body {
            text-align: left;
            font-family: san-serif;
            font-size: 10pt;
            background: #ffffff;
            margin: 0;
        }
        a:link {
            color: #5060B0;
            font-weight: normal;
        }
        a:visited {
            color: #503080;
            font-weight: normal;
        }
        a:hover {
            color:#996699;
            font-weight: normal;
        }
        p.title {
            text-align: left;
            font-size: 14pt;
            font-weight: normal;
            color: #000000;
            background-color: #CCCCCC;
            width: 100%;
            vertical-align: top;
            text-indent: 10px;
        }
        p.error {
            text-align: left;
            font-size: 12pt;
            font-weight: bolder;
            color: #FF0000;
            text-indent: 10px;
        }
        p.menu {
            font-size: 12pt;
            font-weight: bolder;
            color: #000000;
            text-align: center;
        }
        p.section {
            font-size: 14pt;
            font-weight: bolder;
            color: #000000;
            text-align: left;
            text-indent: 30px;
        }
        -->
    </style>
    <body>
    <p class=\"title\">Post-O-Matic - Version ".$versionNumber." - <a href=\"".$websiteUrl."\">".$websiteName."</a></p>
    ";
}
sub print_menu {
    print "
    <p class=\"menu\"><a href=\"postomatic.cgi?action=newEntry\">new entry</a> | edit entry | <a href=\"postomatic.cgi?action=logout\">logout ".$login."</a></p>";
}
sub print_html_content
{
    if (@_[0] eq 'loginForm') {
        print"
        <p class=\"section\"><b>Login<b></p>
        <table border=\"0\" align=\"center\">
            <form action=\"postomatic.cgi\" method=\"post\"> 
            <tr>
                <td>Login:</td><td><input type=\"text\" name=\"login\" size=\"15\"></td>
            </tr>
            <tr>
                <td>Password:</td><td><input type=\"password\" name=\"password\" size=\"15\"></td>
            </tr>
            <tr>
                <td colspan=\"2\"><div align=\"right\">
                    <input type=\"hidden\" name=\"action\" value=\"checkLogin\">
                    <input type=\"submit\" value=\"Submit\">
                </div></td>
            <tr>
            <tr>
                <td colspan=\"2\"><div align=\"center\"><font size=\"-2\">(Please enable cookies and Javascript.)</font></div></td>
            </form> 
        </table>
        ";
    }
    if (@_[0] eq 'newEntry'){
        &print_menu;
        print "<p class=\"section\"><b>New Entry<b></p>
        <table border=\"0\" align=\"center\">
        <form action=\"postomatic.cgi\" method=\"get\">
        <tr>
            <td>File Name:</td>
            <td><input type=\"text\" name=\"fileName\" size=\"20\" maxlength=\"20\">.".$fileExtension."</td>
        </tr>
        <tr>
            <td>Put In:</td>
            <td>
            <select name=\"fileIn\">
                <option value=\"none-selected\" selected>Select...</option>
        ";
                foreach $dir (@directories) {
                    print "<option value=\"/".$dir."\">/".$dir."</option>";
                }
        print "
            </select>
            </td>
        </tr>
        <tr>
            <td>Title:</td>
            <td><input type=\"text\" name=\"title\" size=\"30\"></td>
        </tr>
        <tr>
            <td colspan=\"2\"></td>
        </tr>
        <tr>
            <td colspan=\"2\">Text (HTML)</td>
        </tr>
        <tr>
            <td colspan=\"2\">
                <textarea name=\"text\" rows=\"15\" cols=\"50\"></textarea>
            </td>
        </tr>
        <tr>
            <td colspan=\"2\">
                <input type=\"checkbox\" name=\"convertBreaks\" checked> convert line-breaks
            </td>
        </tr>
        <tr>
            <td colspan=\"2\"><div align=\"right\">
                <input type=\"hidden\" name=\"action\" value=\"previewEntry\">
                <input type=\"submit\" value=\"Preview\">
            </div></td>
        </tr>
        </form>
        </table>
        ";
    }
    if (@_[0] eq 'previewEntry') {
        &print_menu;
        print "<p class=\"section\"><b>Entry Preview<b></p>
        <table border=\"0\" align=\"center\" width=\"80%\">
        <form action=\"postomatic.cgi\" method=\"post\">
        <tr>
            <td>
                Here's how the text of your entry will more-or-less look:
            </td>
        </tr>
        <tr>
            <td>
                <hr />
            </td>
        </tr>
        <tr>
            <td>
            <b><i>".$title."</i></b><br />
            ".$text."
            </td>
        </tr>
        <tr>
            <td>
                <hr />
            </td>
        </tr>";
        $safeTitle = $query->escapeHTML($title);
        $safeText = $query->escapeHTML($text);
        print"
        <tr>
            <td>
                <div align=\"right\">
                <input type=\"hidden\" name=\"fileName\" value=\"".$fileName."\">
                <input type=\"hidden\" name=\"fileIn\" value=\"".$fileIn."\">
                <input type=\"hidden\" name=\"title\" value=\"".$safeTitle."\">
                <input type=\"hidden\" name=\"text\" value=\"".$safeText."\">
                <input type=\"hidden\" name=\"action\" value=\"postEntry\">
                <input type=\"button\" value=\"Return to Editing\" onclick=\"javascript:history.go(-1)\">
                <input type=\"submit\" value=\"POST ENTRY\">
                </div>
            </td>
        </tr>
        </form>
        </table>";
    }
    if (@_[0] eq 'postEntry') {
        &print_menu;
        print"
        <p class=\"section\"><b>Entry Posted Successfully<b></p>
        <table border=\"0\" align=\"center\">
            <tr>
            <td>
            Click <a href=\"".$websiteUrl."\">here</a> to see or <a href=\"postomatic.cgi?action=new\">here</a> to post another.
            </td>
            </tr>
        </table>
        ";
    }
}
sub print_html_bottom {
    print "</body></html>";
}
#other subroutines
sub get_directories { #get directory names
    my $directory = @_[0];
    opendir(DIR, $directory) or $error = "Couldn't open ".$directory." :$!";
    chdir($directory);
    while ($filename=readdir(DIR)) {
        chomp ($filename);
        @filelist=(@filelist,$filename);
        next if ($filename eq ".");
        next if ($filename eq "..");
        if (-d $filename) {
            @directories = (@directories,$filename);
        }
    }
    closedir(DIR);
    return @directories;
}
END;