#!/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"; }