--- /dev/null
+$main::config{base_dir} = '/openils/var/data/offline/';
+$main::config{bootstrap} = '/openils/conf/bootstrap.conf';
--- /dev/null
+#!/usr/bin/perl
+use strict; use warnings;
+
+# --------------------------------------------------------------------
+# Loads the offline script files for a given org, sorts and runs the
+# scripts, and returns the exception list
+# --------------------------------------------------------------------
+
+our $U;
+our %config;
+our $cgi;
+our $base_dir;
+our $logger;
+my @data;
+require 'offline-lib.pl';
+
+my $org = $cgi->param('org');
+my $resp = &process_data( &sort_data( &collect_data() ) );
+&archive_files();
+handle_success("Scripts for org $org processed successfully <br/>" . JSON->perl2JSON($resp) );
+
+
+
+# --------------------------------------------------------------------
+# Collects all of the script logs into an in-memory structure that
+# can be sorted, etc.
+# --------------------------------------------------------------------
+sub collect_data {
+
+ handle_error("Org is not defined") unless $org;
+ my $dir = get_pending_dir($org);
+ handle_error("Batch from org $org is already in process") if (-e "$dir/lock");
+
+ # Lock the pending directory
+ system(("touch", "$dir/lock")) == 0 or handle_error("Unable to create lock file");
+
+ # Load the data from the files
+ my $file;
+ my @data;
+
+ while( ($file = <$dir/*.log>) ) {
+ $logger->debug("offline: Loading script file $file");
+ open(F, $file) or handle_error("Unable to open script file $file");
+ push(@data, <F>);
+ }
+
+ return \@data;
+}
+
+
+# --------------------------------------------------------------------
+# Sorts the commands
+# --------------------------------------------------------------------
+sub sort_data {
+ my $data = shift;
+ $logger->debug("offline: Sorting data");
+ return $data;
+}
+
+
+# --------------------------------------------------------------------
+# Runs the commands and returns the list of errors
+# --------------------------------------------------------------------
+sub process_data {
+ my $data = shift;
+ my $resp = [];
+ for my $d (@$data) {
+ $logger->activity("offline: Executing command $d");
+ }
+ return $resp;
+}
+
+# --------------------------------------------------------------------
+# Moves the script files from the pending directory to the archive dir
+# --------------------------------------------------------------------
+sub archive_files {
+ my $archivedir = create_archive_dir($org);
+ my $pendingdir = get_pending_dir($org);
+ my $err = "Error moving offline logs from $pendingdir to $archivedir";
+ my @files = <$pendingdir/*.log>;
+
+ system( ("rm", "$pendingdir/lock") ) == 0 or handle_error($err);
+ system( ("mv", "@files", "$archivedir") ) == 0 or handle_error($err);
+ system( ("rmdir", "$pendingdir") ) == 0 or handle_error($err);
+ $logger->debug("offline: Archiving files to $archivedir");
+}
+
+
--- /dev/null
+#!/usr/bin/perl
+use strict; use warnings;
+use CGI;
+use OpenSRF::System;
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenILS::Application::AppUtils;
+use JSON;
+
+
+our $U = "OpenILS::Application::AppUtils";
+our %config;
+#do '##CONFIG##/upload-server.pl';
+do 'offline-config.pl';
+our $cgi = new CGI;
+our $base_dir = $config{base_dir};
+my $bsconfig = $config{bootstrap};
+
+
+# --------------------------------------------------------------------
+# Connect to OpenSRF
+# --------------------------------------------------------------------
+OpenSRF::System->bootstrap_client(config_file => $bsconfig);
+
+
+
+
+# --------------------------------------------------------------------
+# Prints out an error message to the client
+# --------------------------------------------------------------------
+sub handle_error {
+ my $err = shift;
+ $logger->error("offline: $err");
+ print "content-type: text/html\n\n";
+ print <<" HTML";
+ <html>
+ <head>
+ <title>Offline Upload Failed</title>
+ </head>
+ <body>
+ <div style='margin-top: 50px; text-align: center;'>
+ <b style='color:red;'>Offline Upload Failed</b><br/>
+ <span> $err </span>
+ </div>
+ </body>
+ </html>
+ HTML
+ exit(1);
+}
+
+
+# --------------------------------------------------------------------
+# Prints out a success message to the client
+# --------------------------------------------------------------------
+sub handle_success {
+ my $msg = shift;
+ $logger->info("offline: returned success message: $msg");
+ print "content-type: text/html\n\n";
+ print <<" HTML";
+ <html>
+ <head>
+ <title>Success</title>
+ </head>
+ <body>
+ <div style='margin-top: 50px; text-align: center;'>
+ <b style='color:blue;'> $msg </b><br/>
+ </div>
+ </body>
+ </html>
+ HTML
+}
+
+
+
+# --------------------------------------------------------------------
+# Fetches and creates if necessary the pending directory
+# --------------------------------------------------------------------
+sub get_pending_dir {
+ my $org = shift;
+ my $dir = "$base_dir/pending/$org/";
+ system( ('mkdir', '-p', "$dir") ) == 0
+ or handle_error("Unable to create directory $dir");
+ $logger->debug("offline: created/fetched pending directory $dir");
+ return $dir;
+}
+
+# --------------------------------------------------------------------
+# Fetches and creates if necessary the archive directory
+# --------------------------------------------------------------------
+sub create_archive_dir {
+ my $org = shift;
+ my (undef,$min,$hour,$mday,$mon,$year) = localtime(time);
+
+ $mon++;
+ $year += 1900;
+ $min = "0$min" unless $min =~ /\d{2}/o;
+ $hour = "0$hour" unless $hour =~ /\d{2}/o;
+ $mday = "0$mday" unless $mday =~ /\d{2}/o;
+ $mon = "0$mon" unless $mon =~ /\d{2}/o;
+
+ my $dir = "$base_dir/archive/$org/$year$mon$mday$hour$min/";
+ system( ('mkdir', '-p', "$dir") ) == 0
+ or handle_error("Unable to create archive directory $dir");
+ $logger->debug("offline: Created archive directory $dir");
+ return $dir;
+}
+
+
+
+# --------------------------------------------------------------------
+# Fetches the workstation object by name
+# --------------------------------------------------------------------
+sub fetch_workstation {
+ my $name = shift;
+ $logger->debug("offline: Fetching workstation $name");
+ my $ws = $U->storagereq(
+ 'open-ils.storage.direct.actor.workstation.search.name', $name);
+ handle_error("Workstation $name does not exists") unless $ws;
+ return $ws;
+}
+
+
--- /dev/null
+#!/usr/bin/perl
+use strict; use warnings;
+
+# --------------------------------------------------------------------
+# Uploads offline action files
+# pending files go into $base_dir/pending/<org>/<ws>.log
+# completed transactions go into $base_dir/archive/<org>/YYYMMDDHHMM/<ws>.log
+# --------------------------------------------------------------------
+
+our $U;
+our %config;
+our $cgi;
+our $base_dir;
+our $logger;
+my $org;
+require 'offline-lib.pl';
+
+if( $cgi->param('file') ) {
+ &load_file();
+ &handle_success("File Upload Succeeded<br/><br/>".
+ "<a href='offline-execute.pl?org=$org'>Execute Scripts for org $org</a>");
+} else {
+ &display_upload();
+}
+
+
+# --------------------------------------------------------------------
+# Use this for testing manual uploads
+# --------------------------------------------------------------------
+sub display_upload {
+
+ my $ws = $cgi->param('ws');
+ my $ses = $cgi->param('ses');
+
+ handle_error("Missing data in upload. We need ws and ses")
+ unless ($ws and $ses);
+
+ print "content-type: text/html\n\n";
+ print <<" HTML";
+ <html>
+ <head>
+ <title>Offline Upload Server</title>
+ <style type='text/css'>
+ input { margin: 5px;' }
+ </style>
+ </head>
+ <body>
+ <div style='margin-top: 50px; text-align: center;'>
+ <form action='offline-upload.pl' method='post' enctype='multipart/form-data'>
+ <b>Testing</b><br/><br/>
+ <b> - Select an offline file to upload - </b><br/><br/>
+ <input type='file' name='file'> </input>
+ <input type='submit' name='Submit' value='Upload'> </input>
+ <input type='hidden' name='ws' value='$ws'> </input>
+ <input type='hidden' name='ses' value='$ses'> </input>
+ </form>
+ </div>
+ </body>
+ </html>
+ HTML
+}
+
+
+
+sub load_file() {
+
+ my $wsname = $cgi->param('ws');
+ my $ses = $cgi->param('ses');
+ my $filehandle = $cgi->upload('file');
+
+ my $ws = fetch_workstation($wsname);
+ $org = $ws->owning_lib;
+ my $dir = get_pending_dir($org);
+ my $output = "$dir/$wsname.log";
+ my $lock = "$dir/lock";
+
+ handle_error("Offline batch in process for this location. Please try again later." ) if( -e $lock );
+ handle_error("File $output already exists" ) if( -e $output );
+
+ $logger->debug("offline: Writing log file $output");
+ open(FILE, ">$output");
+ while( <$filehandle> ) { print FILE; }
+}
+
+
+
+
+