#!/usr/bin/perl
# ##D:/Perl/bin/perl.exe
#
# atomrest.pl - a Perl implementation of the AtomAPI
# draft 6: http://bitworking.org/rfc/draft-gregorio-06.html
#
# future names: dormant.pl or inert.pl (What else do you call an atom at rest?)
#
# by Isofarro
#
# Configuration
# Configuration
#my $fileRoot = "D:/www/default/rest"; # The filesystem root directory
#my $urlRoot = "http://localhost/rest"; # The root URL of the REST folder
#my $scriptRoot = "http://localhost/cgi-bin/atomrest.pl"; # self reference to the REST root
my $fileRoot = "/home/isofarro/public_html/rest"; # The filesystem root directory
my $urlRoot = "http://www.isolani.co.uk/rest"; # The root URL of the REST folder
my $scriptRoot = "http://www.isolani.co.uk/cgi-bin/atomrest.pl"; # self reference to the REST root
# ------------------------------------------------------------------------- #
# Request-Method
my $requestMethod;
# Content-Length of the response body
my $contentLength;
# The XML string
my $xmlString;
# Path Information
my $pathInfo;
init();
if ($requestMethod =~ /^GET$|^POST$|^PUT$|^DELETE$/) {
&doGet if ($requestMethod eq "GET");
&doPost if ($requestMethod eq "POST");
&doPut if ($requestMethod eq "PUT");
&doDelete if ($requestMethod eq "DELETE");
} else {
returnStatusError("400 Bad Request");
}
#debugInfo();
#&debugInfo();
#print end_html;
# ------------------------------------------------------------------------- #
# Atom Functions
# ------------------------------------------------------------------------- #
sub listBlogEntries() {
if (-d "$fileRoot$pathInfo") {
opendir(DIR, "$fileRoot$pathInfo") ||
die "Couldn't open directory $fileRoot$pathInfo: $!\n";
print "Content-Type: text/xml\n\n";
print "\n";
print "\n";
while (defined($file = readdir(DIR))) {
if (-f "$fileRoot$pathInfo$file") {
print "\t\n";
print "\t\t$scriptRoot$pathInfo$file\n";
print "\t\t$scriptRoot$pathInfo$file\n";
print "\t\n\n";
}
}
print "\n";
closedir(DIR);
} else {
returnStatusMessage("404 Not Found");
}
}
# ------------------------------------------------------------------------- #
# HTTP request handers
# ------------------------------------------------------------------------- #
sub doGet() {
if ($pathInfo) {
if (-f "$fileRoot$pathInfo") {
open (ENTRY, "<$fileRoot$pathInfo") ||
die "Couldn't open $fileRoot$pathInfo for writing: $!\n";
print "Content-Type: text/xml\n\n";
while () {
print $_;
}
close(ENTRY);
} elsif (-d "$fileRoot$pathInfo") {
# It may be a root request
&listBlogEntries();
} else {
# TODO redirect back to the blog index via a get
#returnRedirect("");
returnStatusMessage("404 Not Found");
}
} else {
&debugInfo();
#returnStatusMessage("404 Not Found");
}
}
sub doPost() {
if ($pathInfo) {
if (-d "$fileRoot$pathInfo") {
$fileName = &getNewFileName();
open(ENTRY, ">$fileRoot$pathInfo$fileName") ||
die "Couldn't open $fileRoot$pathInfo$fileName for writing: $!\n";
print ENTRY $xmlString;
close(ENTRY);
returnStatusMessage("201 Created");
} else {
returnStatusMessage("520 Bogus Resource");
}
} else {
# No PathInfo, so no REST resource found
returnStatusMessage("404 Not Found");
}
}
sub doPut() {
if ($pathInfo) {
if (-f "$fileRoot$pathInfo") {
open (ENTRY, ">$fileRoot$pathInfo") ||
die "Couldn't open $fileRoot$pathInfo for updating: $!\n";
print ENTRY $xmlString;
close(ENTRY);
returnStatusMessage("201 Created");
} else {
# The actual resource to be updated doesn't exist
returnStatusMessage("404 Not Found");
}
} else {
# No PathInfo so no REST resources found
returnStatusMessage("404 Not Found");
}
}
sub doDelete() {
if ($pathInfo) {
if (-f "$fileRoot$pathInfo") {
unlink("$fileRoot$pathInfo") ||
die "Can't delete $fileRoot$pathInfo: $!\n";
} else {
returnStatusMessage("403 Forbidden");
}
} else {
returnStatusMessage("404 Not Found");
}
}
sub init() {
$requestMethod = $ENV{'REQUEST_METHOD'};
$pathInfo = $ENV{'PATH_INFO'};
# Populate the xmlString on a POST or PUT
if ($requestMethod eq "POST" || $requestMethod eq "PUT") {
$xmlString = getRequestBody();
} else {
$xmlString="";
}
}
sub getRequestBody() {
my ($in);
binmode STDIN;
read(STDIN,$in,$ENV{'CONTENT_LENGTH'}) ||
die "Can't read from STDIN: $!\n";
return $in;
}
sub getNewFileName() {
# Just loop around looking for the next available timestamp
# I probably should do some file locking beforehand incase of simultaneous access
$fileName = time() . ".xml";
while (-e "$fileRoot$pathInfo$fileName") {
sleep(1);
$fileName = time() . ".xml";
}
return $fileName;
}
sub returnStatusMessage() {
my ($msg) = @_;
print "Status: $msg\n\n";
exit();
}
sub debugInfo() {
print "Status: 201 Created\n";
print "Content-type: text/plain\n\n";
print $xmlString;
print "\n\n";
print "PathInfo: $pathInfo\n";
print "RequestMethod: $requestMethod\n";
print "\n";
}