Index: /branches/eam_branches/ipp-pstamp-20260421/pstamp/web/IppPostageStampService.cgi
===================================================================
--- /branches/eam_branches/ipp-pstamp-20260421/pstamp/web/IppPostageStampService.cgi	(revision 42995)
+++ /branches/eam_branches/ipp-pstamp-20260421/pstamp/web/IppPostageStampService.cgi	(revision 42995)
@@ -0,0 +1,1514 @@
+#!/usr/bin/perl
+
+package IppPostageStampService;
+
+use strict;
+use warnings;
+
+use SOAP::Transport::HTTP;
+
+use File::Temp qw( tempfile );
+use File::Basename;
+
+use DBI;
+
+# cached database handle
+my $saved_dbh;
+
+# various configuration paramters for this module
+
+my $dbserver = 'ipp113';
+my $datastore_address = 'http://datastore.ipp.ifa.hawaii.edu';
+
+# http path to workdirs
+my $pstamp_work = 'http://ipp113/pstamp-work';
+
+# nfs path to workdir
+# EAM: does this need to be NFS if apache is local to the disk?
+my $pstamp_workdir = "/export/ipp113.0/pstamp/work";
+
+# NOTE: lin64 below should not be hardwired
+my $psconfdir = "/data/ippc64.1/ippitc/psconfig";
+my $psbuild = "ipp-20170121";
+#my $psbuild = "ipp-trunk-20170221";
+my $buildbin = "$psbuild.lin64/bin";
+
+my $request_label = "PSI";
+
+# Script to set up IPP paths etc to run a command 
+my $pstamp_command = "$psconfdir/$buildbin/pstamp_runcommand.sh $psconfdir $psbuild $pstamp_workdir";
+
+my $previewState = 'parsed';
+my $flesh_out_skycell_id = 1;
+
+# hash to convert submit form paramters to psmkreq parameters
+my $optionsList = {
+    'PSTAMP_SELECT_IMAGE'      =>  '--image',
+    'PSTAMP_SELECT_MASK'       =>  '--mask',
+    'PSTAMP_SELECT_VARIANCE'   =>  '--variance',   
+    'PSTAMP_SELECT_JPEG'       =>  '--jpeg',
+    'PSTAMP_SELECT_CMF'        =>  '--cmf',
+    'PSTAMP_SELECT_PSF'        =>  '--psf',
+    'PSTAMP_SELECT_BACKMDL'    =>  '--backmdl',
+    'PSTAMP_SELECT_UNCOMPRESSED' =>  '--uncompressed',
+    'PSTAMP_SELECT_INVERSE'    =>  '--inverse',
+    'PSTAMP_SELECT_EXPTIME'    => '--exptime',
+    'PSTAMP_SELECT_EXPNUM'     => '--expnum',
+    'PSTAMP_SELECT_EXPTIMEJPEG'    => '--exptimejpeg',
+    'PSTAMP_SELECT_EXPNUMJPEG'     => '--expnumjpeg',
+#    'PSTAMP_SELECT_CONVOLVED'  =>  '--convolved',
+    'PSTAMP_RESTORE_BACKGROUND'=>  '--restorebackground',
+    'PSTAMP_ENABLE_REGENERATION' => '--do_not_wait',
+};
+
+# figure out how to use the real perl RequestFile perl module from cgi
+my @errorStrings = qw(
+PSTAMP_SUCCESS
+PS_EXIT_UNKNOWN_ERROR
+PS_EXIT_SYS_ERROR
+PS_EXIT_CONFIG_ERROR
+PS_EXIT_PROG_ERROR
+PS_EXIT_DATA_ERROR
+PS_EXIT_TIMEOUT_ERROR
+undefined
+undefined
+undefined
+PSTAMP_SYSTEM_ERROR
+PSTAMP_NOT_IMPLEMENTED
+PSTAMP_UNKNOWN_ERROR
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+undefined
+DUPLICATE_REQUEST
+INVALID_REQUEST
+UNKNOWN_PROJECT
+NO_IMAGE_MATCH
+IMAGE_NOT_DESTREAKED
+IMAGE_NOT_AVAILABLE
+IMAGE_GONE
+NO_JOBS_QUEUED
+CENTER_NOT_ON_IMAGE
+PSTAMP_NOT_AUTHORIZED
+NO_VAlID_PIXELS
+BACKGROUND_RESTORE_NOT_AVAILABLE
+);
+
+if (scalar @ARGV) {
+    # if this script is passed any arguments assume that we are doing stand alone testing
+    # do this before invoking the constructor below because it generates errors
+    test(@ARGV);
+    exit 0;
+}
+
+SOAP::Transport::HTTP::CGI
+    -> dispatch_to ('IppPostageStampService')
+    -> options ({compress_threshold => 8192})
+    -> handle;
+
+
+#
+# Functions.
+#
+
+sub getReleaseInfo($$$$) {
+    my ($class, $sessionID, $surveyID) = @_;
+
+#    die ("getReleaseInfo(sessionID, survey_id): incorrect argument count!")
+#           if (@_ != 3);
+
+    my $errorOutput = "getReleaseInfo.ERROR_OUTPUT=";
+    my $verbose = 0;
+
+    my $dbh = getGPC1DBHandle(\$errorOutput);
+
+    if ($dbh) {
+        $errorOutput .= "\n<br>Success: connected with the database<br>\n" if $verbose;
+    } else {
+        $errorOutput .= "<br>Error: failed to connect to the database. $errorOutput\n";
+        return $errorOutput . "<br>";
+    }
+
+  my $query = 
+"SELECT surveyName AS surveyID,
+    release_name, 
+    exp_count as 'exposure_count', 
+    IFNULL(deep_count,0) AS 'deep_stacks',
+    IFNULL(nightly_count, 0) AS 'nightly_stacks',
+    IFNULL(reference_count,0) AS 'reference_stacks',
+    priority, 
+    release_state
+FROM
+
+    (SELECT surveyName, release_name, rel_id, priority, release_state as release_state, count(exp_id) as exp_count 
+      FROM survey JOIN ippRelease USING(surveyID) left join relExp using(rel_id)
+      GROUP BY (rel_id)
+    ) AS surveys
+
+LEFT JOIN
+    (SELECT rel_id, count(stack_id) AS deep_count 
+    FROM relStack where stack_type = 'deep' group by rel_id
+    ) AS ds 
+USING(rel_id)
+
+LEFT JOIN
+(SELECT rel_id, count(stack_id) AS reference_count 
+    FROM relStack where stack_type = 'reference' group by rel_id) 
+    AS rs 
+USING(rel_id)
+
+LEFT JOIN
+(SELECT rel_id, count(stack_id) AS nightly_count 
+    FROM relStack where stack_type = 'nightly' group by rel_id) 
+    AS ns 
+USING(rel_id)
+
+WHERE priority >= 0
+";
+
+  if ($surveyID) {
+    $query .= " AND surveyName = '$surveyID'\n";
+  }
+
+  $query .= "ORDER by surveyName, priority desc\n";
+
+  my $stmt = $dbh->prepare($query);
+  if (!$stmt) {
+    $errorOutput .= "<br>prepare failed for $query<br>";
+    return $errorOutput;
+  }
+  if (!$stmt->execute()) {
+    $errorOutput .= "<br>failed to execute statement " .  $stmt->errstr . "<br>";
+    return $errorOutput;
+  }
+
+  my $result = "RESULT=";
+  if ($stmt->rows > 0) {
+    my $cols = $stmt->{NAME};
+    $result .= arrayToLineOfCols($stmt->{NAME});
+    while (my $row = $stmt->fetchrow_arrayref()) {
+        $result .= arrayToLineOfCols($row);
+    }
+  } else {
+    $result .= "|0|No Releases Found!|\n";
+  }
+
+  return "$errorOutput<br>\n". $result;
+}
+
+# convert an array to a line of columns separated by a '|' characters
+sub arrayToLineOfCols {
+    my $aref = shift;
+    my $result = "";
+    foreach my $col (@$aref) {
+        $result .= "|$col";
+    }
+    $result .= "|\n";
+    return $result;
+}
+
+sub setRequestState($$$$) {
+    my ($class, $sessionID, $req_id, $state) = @_;
+    die ("setRequestState(sessionID, req_id, state): incorrect argument count!")
+           if (@_ != 4);
+    my $errorOutput = "setRequestState.DEBUG_OUTPUT=";
+    my $newState = "";
+
+    # user may only change state to these values
+    if ($state eq 'cancel' or $state eq 'run' or $state eq 'delete') {
+        my $currentState = getRequestState($req_id, \$errorOutput);
+        if ($state eq 'run') {
+            # user may only change state of request in $previewState ('parsed') to run
+            if ($currentState eq $previewState) {
+                $newState = doSetRequestState($req_id, $state, \$errorOutput);
+            } else {
+                $errorOutput .= "ERROR: cannot change request state from $currentState to $state\n";
+            }
+        } elsif ($state eq 'cancel') {
+            # user may only cancel requests in the following states
+            if ($currentState eq 'new' or $currentState eq 'run' or $currentState eq $previewState) {
+                $newState = doSetRequestState($req_id, $state, \$errorOutput);
+            } else {
+                $errorOutput .= "ERROR: cannot change request state from $currentState to $state\n";
+            }
+        } elsif ($state eq 'delete') {
+            # user may only delete requests in the following states
+            if ($currentState eq $previewState or $currentState eq 'stop' 
+             or $currentState eq 'cancel') {
+                # XXX: we could change state of requests in run or new state as well but they might
+                # be being processed which if cleanup is running to zap the workdir out from under the
+                # processing script.
+                # Think about this
+
+                # change state to goto_cleaned
+                $newState = doSetRequestState($req_id, 'goto_cleaned', \$errorOutput);
+            } else {
+                $errorOutput .= "ERROR: cannot change request state from $currentState to $state\n";
+            }
+        }
+    } else {
+        $errorOutput .= "ERROR: Invalid value for new state: $state\n";
+    }
+
+
+    return "$errorOutput NEW_STATE=$newState";
+
+}
+
+
+sub setJobState($$$$) {
+    my ($class, $sessionID, $job_id, $state) = @_;
+    die ("setJobState(sessionID, job_id, state): incorrect argument count!")
+       if (@_ != 4);
+    my $errorOutput = "setJobState.ERROR_OUTPUT=";
+
+    my $newState = "";
+    # user may only change state to these values
+    if ($state eq 'cancel' or $state eq 'run') {
+        my $currentState = getJobState($job_id, \$errorOutput);
+        if ($state eq 'run') {
+            # user may only change state of request in $previewState ('parsed') to run
+            if ($currentState eq $previewState) {
+                $newState = doSetJobState($job_id, $state, \$errorOutput);
+            } else {
+                $errorOutput .= "ERROR: cannot change job state from $currentState to $state\n";
+            }
+        } elsif ($state eq 'cancel') {
+            # user may only cancel requests in the following states
+            if ($currentState eq 'new' or $currentState eq 'run' or $currentState eq $previewState) {
+                $newState = doSetJobState($job_id, $state, \$errorOutput);
+            } else {
+                $errorOutput .= "ERROR: cannot change job state from $currentState to $state\n";
+            }
+        }
+    } else {
+        $errorOutput .= "ERROR: Invalid value for new state: $state\n";
+    }
+
+    return "$errorOutput NEW_STATE=$newState";
+}
+
+sub getRequestState {
+    my $req_id = shift;
+    my $r_errorStr = shift;
+
+    my $dbh = getDBHandle($r_errorStr);
+    if (!$dbh) {
+        return "";
+    }
+
+    if ($req_id =~ /\D/) {
+        $$r_errorStr .= "Error: $req_id is not a valid request id\n";
+        return "";
+    }
+
+    my $query = "SELECT state FROM pstampRequest WHERE req_id = ?";
+
+    my $stmt = $dbh->prepare($query);
+    if (!$stmt) {
+        $$r_errorStr .= "Error: failed to prepare statement $dbh->errstr\n";
+        return "";
+    }
+    if (!$stmt->execute($req_id)) {
+        $$r_errorStr .= "Error: failed to execute statement $stmt->errstr\n";
+        return "";
+    }
+    my $row = $stmt->fetchrow_hashref();
+    if (!$row) {
+        $$r_errorStr .= "Error: failed to find request for $req_id\n";
+        return "";
+    }
+    return $row->{state};
+}
+
+sub doSetRequestState {
+    my $req_id = shift;
+    my $state = shift;
+    my $r_errorStr = shift;
+
+    # XXX: Do not use DBI for this. Implement this in pstamptool
+    my $dbh = getDBHandle($r_errorStr);
+    if (!$dbh) {
+        return "";
+    }
+
+    if ($req_id =~ /\D/) {
+        $$r_errorStr .= "Error: $req_id is not a valid request id\n";
+        return "";
+    }
+
+    my $query = "UPDATE pstampRequest SET state = ? where req_id = ?";
+
+    if ($state eq 'goto_cleaned') {
+        $query .= " AND (state not like '%cleaned')";
+    } else {
+        $query .= " AND (state = 'new' OR state = 'run' OR state ='$previewState')";
+    }
+
+    if (0) {
+        open F, ">/tmp/query.logs" or die "failed to open /tmp/query.logs";
+        print F "$query\n";
+        close F;
+    }
+
+    my $stmt = $dbh->prepare($query);
+    if (!$stmt) {
+        $$r_errorStr .= "Error: failed to prepare statement $dbh->errstr\n";
+        return "";
+    }
+    if (!$stmt->execute($state, $req_id)) {
+        $$r_errorStr .= "Error: failed to execute statement $stmt->errstr\n";
+        return "";
+    }
+
+    return getRequestState($req_id, $r_errorStr);
+}
+
+sub getJobState {
+    my $job_id = shift;
+    my $r_errorStr = shift;
+
+    my $dbh = getDBHandle($r_errorStr);
+    if (!$dbh) {
+        return "";
+    }
+
+    if ($job_id =~ /\D/) {
+        $$r_errorStr .= "Error: $job_id is not a valid request id\n";
+        return "";
+    }
+
+    my $query = "SELECT state FROM pstampJob WHERE job_id = ?";
+
+    my $stmt = $dbh->prepare($query);
+    if (!$stmt) {
+        $$r_errorStr .= "Error: failed to prepare statement $dbh->errstr\n";
+        return "";
+    }
+    if (!$stmt->execute($job_id)) {
+        $$r_errorStr .= "Error: failed to execute statement $stmt->errstr\n";
+        return "";
+    }
+    my $row = $stmt->fetchrow_hashref();
+    if (!$row) {
+        $$r_errorStr .= "Error: failed to find state for $job_id\n";
+        return "";
+    }
+    return $row->{state};
+}
+
+sub doSetJobState {
+    my $job_id = shift;
+    my $state = shift;
+    my $r_errorStr = shift;
+
+    # XXX: Do not use DBI for this. Use pstamptool
+    my $dbh = getDBHandle($r_errorStr);
+    if (!$dbh) {
+        return "";
+    }
+
+    if ($job_id =~ /\D/) {
+        $$r_errorStr .= "Error: $job_id is not a valid request id\n";
+        return "";
+    }
+
+    my $query = "UPDATE pstampJob JOIN pstampRequest USING(req_id) SET pstampJob.state = ? 
+        WHERE job_id = ? AND (pstampJob.state = 'parsed' OR pstampJob.state ='run')
+        AND (pstampRequest.state = '$previewState' OR pstampRequest.state = 'new' OR pstampRequest.state ='run')";
+
+    my $stmt = $dbh->prepare($query);
+    if (!$stmt) {
+        $$r_errorStr .= "Error: failed to prepare statement $dbh->errstr\n";
+        return "";
+    }
+    if (!$stmt->execute($state, $job_id)) {
+        $$r_errorStr .= "Error: failed to execute statement $stmt->errstr\n";
+        return "";
+    }
+
+    return getJobState($job_id, $r_errorStr);
+}
+        
+sub getJobList {
+    my $req_id = shift;
+    my $r_errorStr = shift;
+    my $r_publicURI = shift;
+    my $limit = 0;
+
+    my $dbh = getDBHandle($r_errorStr);
+    if (!$dbh) {
+        return "";
+    }
+
+    if ($req_id =~ /\D/) {
+        $$r_errorStr .= "Error: $req_id is not a valid request id\n";
+        return "";
+    }
+
+    my $listjobs = "
+    SELECT job_id, rownum, exp_id, pstampJob.state, outputBase, pstampJob.fault, pstampJob.fault_count, dep_id,
+         pstampDependent.state as dep_state, pstampDependent.fault as dep_fault,
+         pstampRequest.state as req_state, pstampRequest.outProduct, pstampRequest.name
+    FROM pstampJob JOIN pstampRequest USING(req_id) LEFT JOIN pstampDependent USING(dep_id) WHERE req_id = $req_id
+    ";
+
+    $listjobs .= " LIMIT $limit" if $limit;
+
+    my $stmt = $dbh->prepare($listjobs);
+    if (!$stmt) {
+        $$r_errorStr .= "Error: failed to prepare statement $dbh->errstr\n";
+        return "";
+    }
+    if (!$stmt->execute()) {
+        $$r_errorStr .= "Error: failed to execute statement $stmt->errstr\n";
+        return "";
+    }
+    my $numJobs = 0;
+    my $result = "";
+    my ($product, $req_name, $req_state);
+    while(my $job = $stmt->fetchrow_hashref()) {
+        $product = $job->{outProduct};
+        $req_name = $job->{name};
+        $req_state = $job->{req_state};
+        my $job_id = $job->{job_id};
+        my $rownum = $job->{rownum};
+        my $exp_id = $job->{exp_id};
+        $exp_id = 0 if !defined $exp_id;
+        my $state = $job->{state};
+        my $outputBase = $job->{outputBase};
+        my $base = "";
+        if ($outputBase) {
+            $base = basename($outputBase);
+        }
+        my $fault = $job->{fault};
+        my $errorString = ($fault == 0 ? "" : get_error_string($fault));
+        my $fault_count = $job->{fault_count};
+        my $dep_id = $job->{dep_id};
+        my $dep_state = $dep_id ? $job->{dep_state} : '';
+
+
+        # BEGIN very hacky code to extract information from the outputBase. 
+        # (XXX: This is very intimate with the IPP file rules.
+        # I should be saving this information in pstampJob ...) or otherwise determining in a 
+        # proper manner....
+        my $exp_name   = '';
+        my $stage     = '';
+        my $stage_id  = 0;
+        my $component = '';
+        # base is either in format R_N_F_right or old format without filter R_N_right
+        my (undef, undef, $filter, $right) = split '_', $base;
+        if (defined $filter) {
+            if (length($filter) > 1) {
+                # old format output base does not contain filter
+                $right = $filter;
+                $filter = '';
+            }
+        } else {
+            $filter = '';
+        }
+
+        if (defined $right) {
+            my @w = split '\.', $right;
+            if ($base =~ /summary/) {
+                $stage = 'stack_summary';
+                my $tess_id;
+                $tess_id = $w[0];
+                my $next = 2;
+                if ($w[1] ne 'stk') {
+                    $tess_id .= ".$w[1]";
+                    $next++;
+                }
+                $stage_id = $w[$next];
+                $next += 3;
+                if ($tess_id =~ /RINGS/) {
+                    $component = "skycell.$w[$next]";
+                } else {
+                    $component = "skycell";
+                }
+            } elsif ($base =~ /stk/) {
+                $stage = 'stack';
+                my $tess_id;
+                $tess_id = $w[0];
+                my $next = 2;
+                if ($w[1] ne 'skycell') {
+                    $tess_id .= ".$w[1]";
+                    $next = 3;
+                }
+                if ($tess_id =~ /RINGS/) {
+                    $component = "skycell.$w[$next].$w[$next+1]";
+                    $next += 3;
+                } else {
+                    $component = "skycell.$w[3]";
+                    $next += 2;
+                }
+                $stage_id = $w[$next];
+            } elsif ($base =~ /wrp/) {
+                $stage = 'warp';
+                $exp_name = $w[0];
+                $stage_id = $w[3];
+                $component = "$w[4].$w[5]";
+                if ($w[6]) {
+                    $component .= ".$w[6]";
+                }
+            } elsif ($base =~ /\.ch./) {
+                $stage = 'chip';
+                $exp_name = $w[0];
+                $stage_id = $w[3];
+                $component = $w[4];
+            } elsif ($base =~ /dif/) {
+                $stage = 'diff';
+                my $tess_id = "$w[0].$w[1]";
+                my $next;
+                if ($tess_id =~ /RINGS/) {
+                    $component = "skycell.$w[3].$w[4]";
+                    $next = 5;
+                } else {
+                    $component = "skycell.$w[3]";
+                    $next = 4;
+                }
+                # the diff_id follows 'dif'
+                while ($w[$next]) {
+                    if ($w[$next++] eq 'dif') {
+                        last;
+                    }
+                }
+                $stage_id = $w[$next];
+            } elsif ($base ne '') {
+                $stage = 'raw';
+                $stage_id = $exp_id;
+                $exp_name = $w[0];
+                ($component = $w[1]) =~ s/ota/XY/;
+            }
+        } else {
+            $base = "null";
+        }
+        # END of reverse engineering of job parameters from outputBase
+        # Sorry about that
+
+
+        if ($numJobs++ == 0) {
+            $result = sprintf "|%11s|%24s|%s|%3s|%s|%s|%4s|%s|%s|%s|%s|%11s|%s|%3s|\n", 
+                "job_id", "rownum", "state", "fault", "Error", "stage", "stage_id", "filter", "component", "Frame ID", "exp_id", 
+                "dep_id", "dep_state", "fault_count"; 
+        }
+        if ($exp_id eq 0) {
+            $exp_id = "";
+            $exp_name = "";
+        }
+        if ($dep_id eq 0) {
+            $dep_id = "";
+            $dep_state = "";
+        }
+        if (0) {
+            # such a hacker!
+            print STDERR 
+            "job id is undef\n" unless defined $job_id;
+            print STDERR 
+            "rownum is undef\n" unless defined $rownum;
+            print STDERR 
+            "state is undef\n" unless defined $state;
+            print STDERR 
+            "fault is undef\n" unless defined $fault;
+            print STDERR 
+            "errorString is undef\n" unless defined $errorString;
+            print STDERR 
+            "stage  is undef\n" unless defined $stage;
+            print STDERR 
+            "stage_id is undef\n" unless defined $stage_id;
+            print STDERR 
+            "filter is undef\n" unless defined $filter;
+            print STDERR 
+            "component is undef\n" unless defined $component;
+            print STDERR 
+            "exp_name is undef\n" unless defined $exp_name;
+            print STDERR 
+            "exp_id is undef\n" unless defined $exp_id;
+            print STDERR 
+            "dep_id is undef\n" unless defined $dep_id;
+            print STDERR 
+            "dep_state is undef\n" unless defined $dep_state;
+            print STDERR 
+            "fault_count is undef\n" unless defined $fault_count;
+        }
+        $result .= sprintf "|%11d|%24s|%s|%4d|%s|%s|%s|%s|%s|%s|%s|%11s|%s|%3s|\n", 
+            $job_id, $rownum, $state, $fault, $errorString, $stage, $stage_id, $filter, $component, $exp_name, $exp_id, 
+            $dep_id, $dep_state, $fault_count;
+
+    }
+    if (defined $req_state and $req_state eq 'stop' and $product and $req_name) {
+        $$r_publicURI = buildFilesetURI($datastore_address, $product, $req_name);
+    }
+    return $result;
+}
+
+sub getJobStatusForRequest($$$) {
+    my ($class, $sessionID, $req_id) = @_;
+    die ("getJobStatusForRequest(sessionID, req_id): incorrect argument count!")
+       if (@_ != 3);
+    my $debugOutput = "getJobStatusForRequest.DEBUG_OUTPUT=";
+
+    my $publicURI = "";
+
+    my $job_list = getJobList($req_id, \$debugOutput, \$publicURI);
+
+    return "$debugOutput". "JOB_LIST=$job_list" . "PUBLIC_URI=$publicURI";
+}
+
+sub getFileList {
+    my $job_id = shift;
+    my $r_internalURI = shift;
+    my $r_publicURI = shift;
+    my $r_errorStr = shift;
+    my $limit = 0;
+
+    my $dbh = getDBHandle($r_errorStr);
+    if (!$dbh) {
+        return "";
+    }
+
+    if ($job_id =~ /\D/) {
+        $$r_errorStr .= "Error: $job_id is not a valid job id\n";
+        return "";
+    }
+
+    my $listjobs = "
+    SELECT job_id, pstampJob.state, outputBase, pstampJob.fault, 
+        req_id, pstampRequest.state as req_state, pstampRequest.outProduct, pstampRequest.name
+    FROM pstampJob JOIN pstampRequest using(req_id) WHERE job_id = $job_id
+    ";
+
+    my $stmt = $dbh->prepare($listjobs);
+    if (!$stmt) {
+        $$r_errorStr .= "Error: failed to prepare statement $dbh->errstr\n";
+        return "";
+    }
+    if (!$stmt->execute()) {
+        $$r_errorStr .= "Error: failed to execute statement $stmt->errstr\n";
+        return "";
+    }
+    my $job = $stmt->fetchrow_hashref();
+    if (!$job) {
+        $$r_errorStr .= "Error: failed to find job with $job_id\n";
+        return "";
+    }
+
+    my $job_state = $job->{state};
+    my $req_id = $job->{req_id};
+    my $req_state = $job->{req_state};
+    my $fault = $job->{fault};
+
+    if ($req_state =~ /clean/ or $req_state =~ /canceled/) {
+        $$r_errorStr .= "Error: No files available for job $job_id Request $req_id in state $req_state\n";
+        return "";
+    }
+    if (!($job_state =~ /stop/)) {
+        $$r_errorStr .= "Error: No files available for job $job_id Job in state $job_state\n";
+        return "";
+    }
+    if ($fault != 0) {
+        $$r_errorStr .= "Error: No Files available for faulted job $job_id fault: $fault\n";
+        return "";
+    }
+
+    my $outputBase = $job->{outputBase};
+    if (!$outputBase) {
+        # this is something very strange
+        $$r_errorStr .= "Error: Failed to find outputBase for $job_id\n";
+        return "";
+    }
+
+    # find the directory of internal uri for the request working directory.
+    # The remainder of the string following "work/" in outputBase
+    my $outdir = dirname($outputBase);
+    my $i = index($outdir, 'work');
+    if ($i < 0) {
+        $$r_errorStr .= "Error: Failed to find workdir for $job_id\n";
+        return "";
+    }
+
+    my $workdir = substr($outdir, $i + length('work/'));
+    if (!$workdir) {
+        $$r_errorStr .= "Error: Failed to find workdir for $job_id in string $outdir\n";
+        return "";
+    }
+    $$r_internalURI = $pstamp_work . "/$workdir";
+
+    # If the request is finished also return the public external uri
+    if ($req_state eq 'stop') {
+        my $product = $job->{outProduct};
+        my $name = $job->{name};
+        $$r_publicURI = buildFilesetURI($datastore_address, $product, $name);
+    }
+
+    # read the reglist to get the list of files associated with this job
+    my $reglist = "$outdir/reglist$job_id";
+    if (! -e $reglist ) {
+        $$r_errorStr .= "Error: Failed to locate $reglist\n";
+        return "";
+    }
+    if (! -r $reglist ) {
+        $$r_errorStr .= "Error: Unable to access $reglist\n";
+        return "";
+    }
+    unless (open F, "<$reglist") {
+        $$r_errorStr .= "Error: Unable to open $reglist\n";
+        return "";
+    }
+        
+    my $numFiles = 0;
+    my $result = "";
+    foreach my $f (<F>) {
+        if ($numFiles++ == 0) {
+            $result = sprintf "|filename|size(bytes)|\n";
+        }
+        my ($filename, $size) = split '\|', $f;
+        $result .= sprintf "|%s|%s|\n", $filename, $size;
+    }
+    if ($numFiles == 0) {
+        $$r_errorStr .= "Error: No files for $job_id found in $reglist\n";
+        return "";
+    }
+
+    return $result;
+}
+
+sub getFileListForJob($$$) {
+    my ($class, $sessionID, $job_id) = @_;
+    die ("getFileListForJob(sessionID, req_id): incorrect argument count!")
+           if (@_ != 3);
+
+    my $errorOutput = "";
+    my $internalURI = "";
+    my $publicURI = "";
+    my $file_list = getFileList($job_id, \$internalURI, \$publicURI, \$errorOutput);
+
+    return "getFileListForJob.ERROR_OUTPUT=$errorOutput"
+                . "DEBUG_OUTPUT="
+                . "INTERNAL_BASE_URI=$internalURI" 
+                . "PUBLIC_BASE_URI=$publicURI" 
+                . "FILE_LIST=$file_list";
+}
+
+
+sub getRequestsForUser($$$$$) {
+  my ($class, $sessionID, $username, $date_min, $date_max) = @_;
+
+#  return getJobStatusForRequest($class, $sessionID, 254578);
+
+  die ("getRequestsForUser(sessionID, username, date_min, date_max): incorrect argument count!")
+         if (@_ != 5);
+
+  my $debugOutput = "DEBUG_OUTPUT=";
+  my $verbose = 0;
+
+  $debugOutput .= "Hi from IPP::getRequestsForUser($sessionID, $username, $date_min, $date_max)" if $verbose;
+
+  my $errorStr = "";
+  my $dbh = getDBHandle(\$errorStr);
+
+  if ($dbh) {
+    $debugOutput .= "\n<br>Success: connected with the database<br>\n" if $verbose;
+  } else {
+    $debugOutput .= "<br>Error: failed to connect to the database. $errorStr\n";
+    return $debugOutput . "<br>";
+  }
+
+  my $query = 
+  "SELECT req_id, name, pstampRequest.state, COUNT(distinct rownum) AS numRows,"
+  . "     COUNT(distinct job_id) AS numJobs, registered, timestamp"
+  . " FROM pstampRequest LEFT JOIN pstampJob USING(req_id) LEFT JOIN pstampDependent USING(dep_id)"
+  . " WHERE username = '$username' AND pstampRequest.state NOT LIKE '%cleaned'";
+
+  if ($date_min) {
+    $query .= " AND pstampRequest.registered >= '$date_min'";
+  }
+  if ($date_max) {
+    $query .= " AND pstampRequest.registered < '$date_max'";
+  }
+
+  $query .= " GROUP by req_id ORDER BY req_id DESC";
+
+  # $debugOutput .= "<br>QUERY=$query\n<br>";
+
+  my $stmt = $dbh->prepare($query);
+  if (!$stmt) {
+    $debugOutput .= "<br>prepare failed for $query<br>";
+    return $debugOutput;
+  }
+  if (!$stmt->execute()) {
+    $debugOutput .= "<br>failed to execute statement " .  $stmt->errstr . "<br>";
+    return $debugOutput;
+  }
+
+  my $result = "RESULT=";
+  if ($stmt->rows > 0) {
+    $result .= "|req_id|req_name|state|numRows|numJobs|Submit time|last state change|\n";
+    while (my @cols = $stmt->fetchrow_array()) {
+        $result .= "\n";
+        foreach my $col (@cols) {
+            $col = 'null' if !defined $col;
+            $result .= "|$col";
+        }
+        $result .= "|\n";
+    }
+  } else {
+    $result .= "|0|No matching requests found|\n";
+  }
+
+  return "$debugOutput<br>". $result;
+}
+
+
+sub requestPreview($$$) {
+  my ($class, $sessionID, $previewRequest) = @_;
+  #print "Creating SOAP PostageStampService object...\n" ;
+
+  die ("requestPreview(sessionID, previewRequest): incorrect argument count!")
+       if (@_ != 3);
+
+  my $debugOutput = "";
+  my $errorOutput = "";
+
+  my $displayRequest = 1;
+  if ($displayRequest) {
+    $debugOutput .= "sessionID: " . $sessionID .
+              ", request: " . $previewRequest . "<br>\n";
+  }
+
+  my %params = getPreviewRequestParams($previewRequest);
+
+  my $echoParams = 1;
+  if ($echoParams) {
+    $debugOutput .= "<br>\nRequest Parameters:<br>\n";
+    while (my ($key, $val) = each %params) {
+      $debugOutput .= $key . " => " . $val . "<br>\n";
+    }
+    $debugOutput .= "<br><br>\n";
+  }
+
+  my $dump_env = 0;
+  if ($dump_env) {
+    # dump environnment
+    foreach my $v (sort keys %ENV) {
+      my $val = $ENV{$v};
+      $debugOutput .=  " $v = '$val'<br>\n";
+    }
+    $debugOutput .= "<br><br>\n";
+  }
+
+  my $username = $params{username};
+
+  my $user_req_name = $params{name};
+
+  my $action = $params{ACTION};
+
+  my $request_prefix = $user_req_name ? $user_req_name : 'PSI';   # we were using email address but that seems insecure
+  {
+    my @words = split /\s+/, $request_prefix;
+    if (scalar @words != 1) {
+        $errorOutput .= "ERROR: '$request_prefix' is not a valid Request Name\n";
+        return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+    }
+  }
+  # This command submits a postage stamp request.
+  # The initial parameters are consumed by the script. 
+  my $label = $request_label;
+  $label = 'TEST' if $params{PSTAMP_TEST_MODE};
+  my $cmd = "pstamp_webrequest.pl --dbserver $dbserver --dbname ippRequestServer --label $label --prefix $request_prefix";
+  $cmd .= " --username $username";
+
+  # Beginning here, the parameters are passed to psmkreq - the command that builds the request fits table
+  $cmd .= " --email $username" if $username;
+  $cmd .= " --action PREVIEW" if uc($action) eq 'PREVIEW';
+
+  # set to 1 to submit request to the server for processing
+  # if zero just test that the request file builds properly
+  my $submit = 1;
+  unless ($submit) {
+    $cmd .= " --pretend";
+  }
+
+  my $stage = $params{ImageType};
+  unless ($stage eq 'stack' or $stage eq 'warp' or $stage eq 'chip' or $stage eq 'diff' or $stage eq 'raw' or $stage eq 'stack_short') {
+    $errorOutput .= "ERROR: $stage is not a valid ImageType\n";
+    return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+  }
+
+  # apply fwhm cuts if supplied unless one of the other parameters causes it to not make sense
+  my $apply_fwhm = 1;
+
+  my $run_type;
+  if ($stage eq 'stack_short') {
+    $stage = 'stack';
+    $run_type = 'nightly';
+    # XXX: nightly stacks do now have fhwm measurements so we silently ignore them if supplied
+    # This may not be true in the future
+    $apply_fwhm = 0;
+  } elsif ($stage eq 'stack') {
+    # add a selector to explicitly say deep or reference
+    # For now use special code that tells request parser to avoid nightly stacks
+    $run_type = 'notnightly';
+  } elsif ($stage eq 'diff') {
+      my $diff_type = $params{PSTAMP_DIFF_TYPE};
+      if ($diff_type) {
+        $run_type = $diff_type;
+      }
+  }
+
+  $cmd .= " --stage $stage";
+  $cmd .= " --run_type $run_type" if $run_type;
+
+  my $survey = $params{SurveyID};
+
+  my $skycell_id = $params{skycellID};
+  if (defined($skycell_id) and $flesh_out_skycell_id and length($skycell_id) and ($skycell_id ne 'all')) {
+    # as a convienience, allow user the user to leave off the 'skycell.' prefix in the skycell_id
+    # no error checking is performed
+    if (! ($skycell_id =~ /^skycell\./)) {
+        # skycell_id does not begin with 'skycell.'
+        if ($survey =~ /MD/) {
+            if (! ($skycell_id =~ /\D/)) {
+                # supplied skycell is just a number go for it making sure that
+                # it has a zero prepended if < 100
+                $skycell_id = sprintf "skycell.%03d", $skycell_id;
+            }
+        } else {
+            # just prepend 'skycell.' It's up to the user to supply a correct DDDD.DDD value
+            $skycell_id = "skycell.$skycell_id";
+        }
+    }
+  }
+
+  my $otaID = $params{otaID};
+
+  my $req_type;
+  my $source = $params{ImageSource};
+
+  if (!defined $source) {
+    $errorOutput .= "ERROR: ImageSource is required\n";
+    return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+
+  } elsif ($source eq 'coord') {
+    $req_type = "bycoord";
+
+  } elsif ($source eq 'exposure') {
+    $req_type = 'byexp';
+    if ($stage eq 'diff') {
+        $survey = undef;
+    }
+    my $exp_name = $params{exposureID};
+    unless ($exp_name) {
+      $errorOutput .= "ERROR: exposureID is required with ImageSource: Exposure\n";
+      return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+    }
+    $cmd .= " --id $exp_name";
+    $apply_fwhm = 0;            # no cuts for byexp
+
+  } elsif ($source eq 'id') {
+    $req_type = 'byid';
+    my $id = $params{ImageSourceID};
+    unless ($id) {
+      $errorOutput .= "ERROR: ImageSourceID is required with ImageSource: imagesource\n";
+      return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+    }
+    $cmd .= " --id $id";
+    $apply_fwhm = 0;            # no cuts for byid
+
+  } elsif ($source eq 'skycell') {
+    if (!$skycell_id) {
+      $errorOutput .= "ERROR: skycellID is required with ImageSource: skycell\n";
+      return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+    }
+    $req_type = 'byskycell';
+
+  } else {
+    $errorOutput .= "ERROR: $source is not a valid ImageSource\n";
+    return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+  }
+
+  $cmd .= " --req_type $req_type";
+
+  my $rangeType = $params{rangeType};
+  my ($w, $h);
+  unless (defined $rangeType) {
+    $errorOutput .= "ERROR: rangeType is required\n";
+    return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+  }
+
+  if ($rangeType eq 'pixel') {
+    $w = $params{pixelW};
+    $h = $params{pixelH};
+
+    unless (length($w) and length($h)) {
+      $errorOutput .= "ERROR: pixelW and pixelH are required\n";
+      return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+    }
+  } else {
+    $w = $params{rangeRa};
+    $h = $params{rangeDec};
+    unless (length($w) and length($h)) {
+      $errorOutput .= "ERROR: rangeRa and rangeDec are required\n";
+      return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+    }
+    $cmd .= ' --arcseconds';
+  }
+
+  if ($h < 0 || ($w == 0 and $h != 0)) {
+    $errorOutput .= "Error: invalid height\n";
+    return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+  } elsif ($w < 0 || ($h == 0 and $w != 0)) {
+    $errorOutput .= "Error: invalid width\n";
+    return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+  }
+  $cmd .= " --width $w --height $h";
+  if ($req_type ne 'bycoord' and $w == 0 and $h == 0) {
+    $cmd .= " --pixcenter";
+  }
+
+  # if ($req_type ne "byid" and $stage ne 'diff') {
+  if ($req_type ne "byid") {
+      my $release = $params{ReleaseName};
+      if ($stage ne 'diff') {
+      #    if (!defined $survey) {
+      #        $errorOutput .= "ERROR: SurveyID is required\n";
+      #        return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+      #    }
+          # we allow blank survey now to handle byexp requests for exposures that were
+          # processed as part of SSS and 3PI.PV3
+          $cmd .= " --survey $survey"   if $survey;
+          $cmd .= " --release $release" if $release;
+      } else {
+          # diff stage does not (yet) have corresponding release tables
+          # hack around the absence of release tracking.
+          # default to nightly science data group
+          # 3PI.PV3 diffs do not have images
+          if ($survey eq '3PI') {
+              $cmd .= " --data_group ThreePi.20%";
+          } elsif ($survey =~ /MD/) {
+              $cmd .= " --data_group $survey.20%";
+          } elsif ($survey eq 'SSS') {
+              $cmd .= " --data_group %SS.20%";
+          }
+      }
+  }
+
+  if ($stage eq 'stack' or $stage eq 'warp' or $stage eq 'diff') {
+      # Apply a tess_id supplied by the user.
+      my $tess_id = $params{tessellationID};
+      if (!$tess_id and $stage eq 'stack' and ($survey eq '3PI' or $survey eq 'SSS')) {
+          # all 3PI and SSS stacks use RINGS.V3
+          $tess_id = 'RINGS.V3';
+      }
+      if ($tess_id) {
+        $cmd .= " --tess_id $tess_id";
+      }
+      # select skycell
+      if ($skycell_id) {
+        $cmd .= " --component $skycell_id";
+      }
+  }
+
+  if ($stage eq 'chip') {
+    if ($otaID) {
+        $cmd .= " --component $otaID";
+    }
+  }
+  if ($apply_fwhm) {
+    my $fwhm_min = $params{PSTAMP_FWHM_MIN};
+    if ($fwhm_min) {
+        $cmd .= " --fwhm_min $fwhm_min";
+    }
+    my $fwhm_max = $params{PSTAMP_FWHM_MAX};
+    if ($fwhm_max) {
+        $cmd .= " --fwhm_max $fwhm_max";
+    }
+  }
+
+  my $dataProductsAndOptions = selectDataProductsAndOptions(\%params, \$errorOutput);
+  if (!$dataProductsAndOptions) {
+    $errorOutput = "<br>ERROR no data products or options selected<br>\n" . $errorOutput;
+    
+    return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+  }
+
+  $cmd .= " $dataProductsAndOptions";
+    
+  my $entireFilter = $params{entireFilter};
+  if ($entireFilter) {
+     # request is for entire image skip coord list
+     $cmd .= " --whole-file";
+
+     if ($entireFilter ne 'a') {
+        $cmd .= " --filter $entireFilter";
+     }
+  }
+  # } else {
+  if ($params{coordList}) {
+     # convert the coordList paramter into a list of rows in the format that
+     # psmkreq accepts
+     my $coordList = $params{coordList};
+     my $coordCount = $params{coordCount};
+
+     if (0) {
+       my $fn = "/tmp/coordlist." . time();
+         open OUT, ">$fn";
+         print OUT "$coordList\n";
+         close OUT;
+     }
+
+     my @rows = parseCoordList($coordList);
+
+     my $nrows = scalar @rows;
+     if ($nrows != $coordCount) {
+       $errorOutput .= "ERROR: coordCount: $coordCount but only parsed $nrows\n";
+       return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+     }
+
+     # write the coordinate list to a temporary file
+     my $save_temps = 0;
+     my ($listfile, $listfileName) = tempfile( "/tmp/coordlist.XXXX", UNLINK => !$save_temps) ;
+     foreach my $row (@rows) {
+       print $listfile "$row |\n";
+     }
+     close $listfile;
+
+     $cmd .= " --list $listfileName";
+   }
+
+#  $cmd .= " --save-temps";
+
+  $cmd = "$pstamp_command $cmd";
+
+  # $cmd .= " | tee -a /tmp/command_log";
+
+  my $displayCommand = 1;
+  if ($displayCommand) {
+    $debugOutput .= "Command to build request file is: $cmd\n<br>";
+  }
+
+  if (1) {
+    open FOO, '>>', '/tmp/command.log' or die "failed to open command log\n";
+    print FOO $debugOutput;
+    close FOO;
+  }
+
+  if (0) {
+    # send debugOutput to the apache error log
+    print STDERR $debugOutput;
+  }
+
+  if (1) {
+    # run the command and parse the results
+    my $useipcrun = 0;
+    # IPC::Cmd is not installed on the system so we can't use it
+    if ($useipcrun) {
+      my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =
+          run(command => $cmd, verbose => 0);
+      unless ($success) {
+        my $status = $error_code >> 8;
+        $errorOutput .= "ERROR: command returned $error_code $status\n<br>";
+        return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+      }
+      my ($req_id, $req_name) = split " ", join "", @$stdout_buf;
+      chomp $req_id;
+      if (!$req_id) {
+        $errorOutput .= "ERROR: didn't receive error_code \n<br>";
+        return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+      }
+      return makeSubmitResponse('SUCCESS', $req_id, $req_name, $errorOutput, $debugOutput);
+    } else {
+      my $result = `$cmd`;
+      if ($?) {
+        $errorOutput .= "ERROR: command returned $? result: $result\n<br>";
+        return makeSubmitResponse('ERROR_INTERNAL', 0, 0, $errorOutput, $debugOutput);
+      }
+      if (!$result) {
+        $errorOutput .= "ERROR: command succeded but reruned no output\n<br>";
+        return makeSubmitResponse('ERROR_INTERNAL', 0, 0, $errorOutput, $debugOutput);
+      }
+        
+      my ($req_id, $req_name) = split " ", $result;
+      if (!$req_id) {
+        $errorOutput .= "ERROR: command succeded but no valid req_id found\n<br>";
+        return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+      }
+      if (!$req_name) {
+        $errorOutput .= "ERROR: command succeded req_id: $req_id but no req_name found\n<br>";
+        return makeSubmitResponse('ERROR_REQ', 0, 0, $errorOutput, $debugOutput);
+      }
+      return makeSubmitResponse('SUCCESS', $req_id, $req_name, $errorOutput, $debugOutput);
+    }
+  } else {
+    $debugOutput .= "Request submission disabled<br>";
+    return makeSubmitResponse('SUCCESS', 0, 0, $errorOutput, $debugOutput);
+  }
+
+  #return SOAP::Data->name('return')->type('string')->value($response);
+}
+
+# convert params string into a hash
+sub getPreviewRequestParams() {
+    my ($req) = @_;
+    my %params_hash;
+    my ($p, $key, $val);
+    my @params = split('&', $req);
+
+    foreach $p (@params) {
+        ($key, $val) = split('=', $p);
+	$params_hash{$key} = $val;
+        # print $key . ": " . $val . "\n";
+    }
+
+    return %params_hash;
+}
+
+
+# convert coordinate list to the format accepted by psmkreq
+sub parseCoordList {
+    my $coordList = shift;
+
+    # psmkreq takes a space delimited list
+    $coordList =~ s/,/ /g;
+    # change nulls to zeros (mjd)
+    $coordList =~ s/null/0/g;
+    # change a to null (for all filters)
+    $coordList =~ s/a/null/g;
+
+    # Now split into rows
+    #my @rows = split /\|/, $coordList;
+    # change by Thomas, use '#' instead of '|', to avoid conflict with '|' in return.
+    my @rows = split /#/, $coordList;  
+
+    return @rows;
+}
+
+
+sub selectDataProductsAndOptions {
+  my $params = shift;
+  my $r_response = shift;
+
+  my $imageType = $params->{ImageType};
+
+  my $options = "";
+  foreach my $option (keys %$optionsList) {
+    # $$r_response .= "<br>$option";
+    my $value = $params->{$option};
+    if (defined $value) {
+      unless ($option eq 'PSTAMP_ENABLE_REGENERATION') {
+        if ($value) {
+          $options .= " $optionsList->{$option}";
+        }
+      } else {
+        # unless the image type is stack, if PSSTAMP_ENABLE_REGENERATION is not set pass the 'no wait' option
+        # (For debugging purposes, I don't want to see that unfamiliar bit in the
+        # option mask when it will not be apply)
+        if ($imageType ne 'stack' and $imageType ne 'stack_summary' and !$value) {
+          $options .= " $optionsList->{$option}";
+        }
+      }
+    }
+  }
+  return $options;
+}
+
+# This was a temporary hack to allow MD refstacks to be retrieved prior to the
+# definition of the MD releases
+sub getDataGroup {
+    my $survey = shift;
+
+    my $data_group;
+    my $tess_id;
+    if ($survey eq 'MD01') {
+        $data_group = 'MD01.refstack.20120803';
+        $tess_id = 'MD08.V3';
+    } elsif ($survey eq 'MD02') {
+        $data_group = 'MD02.refstack.20120927';
+        $tess_id = 'MD02.V3';
+    } elsif ($survey eq 'MD03') {
+        $data_group = 'MD03.refstack.20121101';
+        $tess_id = 'MD03.V3';
+#    } elsif ($survey eq 'MD03') {
+#        $data_group = 'MD03.refstack.20121101redo';
+#        $tess_id = 'MD03.V3';
+    } elsif ($survey eq 'MD04') {
+        $data_group = 'MD04.refstack.20121125';
+        $tess_id = 'MD04.V3';
+    } elsif ($survey eq 'MD05') {
+        $data_group = 'MD05.refstack.20121202';
+        $tess_id = 'MD05.V3';
+    } elsif ($survey eq 'MD06') {
+        $data_group = 'MD06.refstack.20121221';
+        $tess_id = 'MD06.V3';
+    } elsif ($survey eq 'MD07') {
+        $data_group = 'MD07.refstack.20130102';
+        $tess_id = 'MD07.V3';
+#    } elsif ($survey eq 'MD07') {
+#        $data_group = 'MD07.refstack.20130102redo';
+#        $tess_id = 'MD07.V3';
+    } elsif ($survey eq 'MD08') {
+        $data_group = 'MD08.refstack.20130401';
+        $tess_id = 'MD08.V3';
+    } elsif ($survey eq 'MD09') {
+        $data_group = 'MD09.refstack.20120831';
+        $tess_id = 'MD09.V3';
+    } elsif ($survey eq 'MD10') {
+        $data_group = 'MD10.refstack.20120804';
+        $tess_id = 'MD10.V3';
+    }
+
+    return ($data_group, $tess_id)
+}
+
+sub makeSubmitResponse {
+  my $resultCode = shift;
+  my $req_id = shift;
+  my $req_name = shift;
+  my $errorOutput = shift;
+  my $debugOutput = shift;
+
+  $debugOutput = "" unless defined $debugOutput;
+  $errorOutput = "" unless defined $errorOutput;
+
+  my $success = 0;
+  unless ($resultCode) {
+    $resultCode = "ERROR_INTERNAL";
+    $errorOutput = "No result code";
+  } elsif ($resultCode eq 'SUCCESS') {
+      $success = 1;
+  }
+
+  if ($success and !$req_id) {
+    $resultCode = "ERROR_INTERNAL";
+    $errorOutput = "No req_id";
+    $success = 0;
+  }
+
+  if ($success and !$req_name) {
+    $resultCode = "ERROR_INTERNAL";
+    $errorOutput = "No req_name";
+    $success = 0;
+  }
+
+  my $response;
+  if ($success) {
+    $response .= "$resultCode|$req_id|$req_name|$errorOutput|$debugOutput|"
+  } else {
+    $response .= "$resultCode|0|0|$errorOutput|$debugOutput|"
+  }
+
+  return $response;
+}
+
+# construct a fileset uri from the product and name
+sub buildFilesetURI {
+    my ($datastore, $product, $name) = @_;
+    return "$datastore/$product/$name";
+}
+
+sub getDBHandle {
+    my $r_error = shift;
+    if ($saved_dbh) {
+        return $saved_dbh;
+    }
+
+    my $dbname = "ippRequestServer";
+    my $dbuser = "NOT_SET";
+    my $dbpassword = "NOT_SET";
+
+    my $dsn = "DBI:mysql:host=$dbserver;database=$dbname";
+
+    my $saved_dbh = DBI->connect($dsn, $dbuser, $dbpassword) ;
+
+    if (!$saved_dbh) {
+        $$r_error = $DBI::errstr . "\n";
+    }
+
+    return $saved_dbh;
+}
+
+sub getGPC1DBHandle {
+    my $r_error = shift;
+    if ($saved_dbh) {
+        return $saved_dbh;
+    }
+
+    my $dbname = "gpc1";
+    my $dbserver = "scidbm";
+    my $dbuser = "NOT_SET";
+    my $dbpassword = "NOT_SET";
+
+    my $dsn = "DBI:mysql:host=$dbserver;database=$dbname";
+
+    my $saved_dbh = DBI->connect($dsn, $dbuser, $dbpassword) ;
+
+    if (!$saved_dbh) {
+        $$r_error = $DBI::errstr . "\n";
+    }
+
+    return $saved_dbh;
+}
+
+# stand alone test for the getFileList function
+sub test_getFileList {
+    my @jobs_ids = (37813088, 37977840);
+
+    foreach my $job_id (@jobs_ids) {
+        my $errstr = "";
+        my $internalURI = "";
+        my $publicURI ="";
+        my $r = getFileList($job_id, \$internalURI, \$publicURI, \$errstr);
+
+        if ($internalURI) {
+            print "INTERNAL_BASE_URI=$internalURI PUBLIC_BASE_URI=$publicURI\n";
+        }
+        if ($r) {
+            print $r;
+        }
+        if ($errstr) {
+            print $errstr;
+        }
+    }
+}
+
+sub get_error_string {
+    my $error_code = shift;
+    my $error_string;
+    if ($error_code >= 0) {
+        $error_string = $errorStrings[$error_code];
+    }
+    $error_string = "unknown" if !$error_string;
+    return $error_string;
+}
+
+
+sub test_setRequestState {
+    my $results = setRequestState("", "", 263456, "run");
+
+    print "$results\n";
+}
+sub test_setJobState {
+    my $results = setJobState("", "", 38115107, "cancel");
+
+    print "$results\n";
+}
+sub test_getReleaseInfo {
+    # my $results = getReleaseInfo("this", "dummySession", '3PI', '');
+    my $results = getReleaseInfo("this", "dummySession", '', '');
+    print "$results\n";
+}
+sub test_getErrorStr {
+    my $code = shift;
+    my $str = get_error_string($code);
+    print "$code $str\n";
+}
+sub test {
+    # test_setRequestState();
+    # test_setJobState();
+    test_getReleaseInfo()
+    #test_getErrorStr(26);
+    #test_getErrorStr(28);
+}
