#!/usr/local/bin/perl -T # "Simplified Perl Status Poster" # # MIT License # # Copyright (c) 2023 Samir Parikh # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. use warnings; use strict; use lib "/home/compiler/perl5/lib/perl5"; use JSON; use POSIX qw( strftime ); use Data::Dumper; use CGI; use Text::Markdown; use File::Spec::Functions; use feature qw( signatures ); no warnings qw( experimental::signatures ); # declare constants ### path to spsp directory my $SPSP_PATH = "/home/compiler/programs/spsp"; ### file to store json-formatted post history in reverse chronological order my $POST_DATA_FILENAME = "$SPSP_PATH/html/post_data"; ### temporary file used to create updated post_data json file my $POST_DATA_TEMP_FILENAME = "$SPSP_PATH/html/post_data_temp.$$"; ### HTML file for all fo our posts my $POSTS_HTML_FILENAME = "$SPSP_PATH/html/posts.html"; my $POSTS_REL_PATH_FILENAME = "/posts.html"; ### temporary HTML file we use to update posts.html based on data from post_data my $POSTS_TEMP_HTML_FILENAME = "$SPSP_PATH/html/posts_temp.html.$$"; ### path for new HTML file for our most recent post my $NEW_POST_HTML_PATH = "$SPSP_PATH/html/"; ### length of random ID assigned to each post my $ID_LENGTH = 4; ### hash key constants my $ID = "id"; my $TITLE = "title"; my $STATUS = "status"; my $TIMESTAMP = "timestamp"; ### HTML constants my $HTML_TITLE = "SPSP"; my $APPLICATION = "Simple Perl Status Poster"; my $AUTHOR = "Samir Parikh"; my $HEADING = "Samir's Updates"; my $cgi = CGI->new; my $markdown_to_html = Text::Markdown->new; sub generate_post_id ( $id_length ) { my @characters = (0 .. 9, "a" .. "z"); return join '', map $characters[ rand @characters ], 1 .. $id_length; } ### check to see if post_data file exists. If not, create it unless ( -e $POST_DATA_FILENAME ) { open my $post_data_filehandle, '>>', $POST_DATA_FILENAME or die "Cannot open $POST_DATA_FILENAME for appending: $!\n"; close $post_data_filehandle or die "Error closing $POST_DATA_FILENAME: $!\n"; } ### open post data file for reading open my $post_data_filehandle, '<', $POST_DATA_FILENAME or die "Cannot open $POST_DATA_FILENAME for reading: $!\n"; ### read all current posts into @posts my $json_posts = JSON->new; my @posts = do { local $/; @{ $json_posts->decode( <$post_data_filehandle> ) }; }; ### close post data file close $post_data_filehandle or die "Cannot close $POST_DATA_FILENAME: $!\n"; ### assemble the new post into a hash my $new_post = { $ID => generate_post_id( $ID_LENGTH ), $TITLE => scalar $cgi->param( $TITLE ), $STATUS => scalar $cgi->param( $STATUS ), $TIMESTAMP => strftime "%a %d %b %Y %H:%M %Z", localtime, }; ### prepend new post to the array of posts unshift @posts => $new_post; # write updated posts to temporary file ### open temporary file for writing open my $temp_filehandle, '>', $POST_DATA_TEMP_FILENAME or die "Cannot open $POST_DATA_TEMP_FILENAME for writing: $!\n"; my $posts = $json_posts->pretty->encode( \@posts ); print $temp_filehandle $posts; ### close the temporary file close $temp_filehandle or die "Error closing $POST_DATA_TEMP_FILENAME: $!\n"; ### delete original post data file unlink $POST_DATA_FILENAME or die "Cannot delete original $POST_DATA_FILENAME: $!\n"; ### Rename temporary file to replace original post data file rename $POST_DATA_TEMP_FILENAME, $POST_DATA_FILENAME or die "Cannot rename $POST_DATA_TEMP_FILENAME to $POST_DATA_FILENAME: $!\n"; ### recreate new posts.html file by first opening and creating temporary file open $temp_filehandle, '>', $POSTS_TEMP_HTML_FILENAME or die "Cannot open $POSTS_TEMP_HTML_FILENAME for writing: $!\n"; ### change default output filehandle select $temp_filehandle; print <<"EOF"; $HTML_TITLE

$APPLICATION

$HEADING


EOF foreach my $post ( @posts ) { print "

{ $ID }.html\">$post->{ $TITLE }\n" unless ( $post->{ $TITLE } eq '' ); my $html = $markdown_to_html->markdown( $post->{ $STATUS } ); print $html, "\n"; print "

{ $ID }.html\">$post->{ $TIMESTAMP }\n"; print "


\n"; } print "\n"; print "\n"; ### change back to default output filehandle select STDOUT; ### close the temporary file close $temp_filehandle or die "Error closing $POSTS_TEMP_HTML_FILENAME: $!\n"; ### delete original posts.html file unlink $POSTS_HTML_FILENAME or die "Cannot delete original $POSTS_HTML_FILENAME: $!\n"; ### rename temporary posts html file to replace original post data file rename $POSTS_TEMP_HTML_FILENAME, $POSTS_HTML_FILENAME or die "Cannot rename $POSTS_TEMP_HTML_FILENAME to $POSTS_HTML_FILENAME: $!\n"; ### open filehandle to create HTML file for new post my $new_post_html = catfile( $NEW_POST_HTML_PATH, "$new_post->{ $ID }.html" ); open my $new_post_filehandle, '>', $new_post_html or die "Cannot open $new_post_html for writing: $!\n"; ### change default output filehandle select $new_post_filehandle; print <<"EOF"; $HTML_TITLE

$APPLICATION

$HEADING


EOF print "

{ $ID }.html\">$new_post->{ $TITLE }\n" unless ( $new_post->{ $TITLE } eq '' ); my $html = $markdown_to_html->markdown( $new_post->{ $STATUS } ); print $html, "\n"; print "

{ $ID }.html\">$new_post->{ $TIMESTAMP }\n"; print "


\n"; print "\n"; print "\n"; ### change back to default output filehandle select STDOUT; ### close the temporary file close $new_post_filehandle or die "Error closing $new_post_html: $!\n"; print $cgi->redirect( $POSTS_REL_PATH_FILENAME ); exit 0;