#!/usr/bin/perl # # fdsnws-event handler: # # A test and template handler for the NCEDC Web Service Shell (WSS) # implementing fdsnws-event version 1.0. # # This handler validates and processes a request and responds as # expected by the WSS using a NCEDC web service to fulfill the request. # # Data requests are submitted as command line arguments. All returned # data is written to STDOUT and all diagnostics and errors are written # to STDERR. # ## Use as a template # # To modify this handler to access local data center repositories the # HandleRequest() routine should be modified, replacing the call to a # NCEDC web service with data extraction from local repositories or # whatever else might be appropriate. # # The exit statuses employed and expected by the WSS: # # Exit Status = Description # 0 = Successfully processed request, data returned via stdout # 1 = General error. An error description may be provided on stderr # 2 = No data. Request was successful but results in no data # 3 = Invalid or unsupported argument/parameter # 4 = Too much data requested # # All start times and end times are assumed to be in UTC and expected # in be one of these forms (with optional trailing Z): # YYYY-MM-DD[T]HH:MM:SS.ssssss # YYYY-MM-DD[T]HH:MM:SS # # ChangeLog: # # 2013.119: # - Initial version use Env qw( ORACLE_HOME NLS_LANG NLS_DATE_FORMAT ); use strict; use Getopt::Long; use File::Basename; use Config; use LWP::UserAgent; use HTTP::Status qw(status_message); use HTTP::Date; my $version = "2013.035"; my $scriptname = basename($0); my $verbose = undef; my $usage = undef; my $pretend = undef; my $starttime = '1900-01-01T00:00:00'; my $endtime = '2030-01-01T00:00:00'; my $minlatitude = undef; my $maxlatitude = undef; my $minlongitude = undef; my $maxlongitude = undef; my $latitude = undef; my $longitude = undef; my $minradius = undef; my $maxradius = undef; my $mindepth = undef; my $maxdepth = undef; my $minmagnitude = undef; my $maxmagnitude = undef; my $magnitudetype = undef; my $includeallmagnitudes = undef; my $includearrivals = undef; my $includemechanisms = undef; my $eventid = undef; my $limit = undef; my $offset = undef; my $orderby = undef; my $catalog = undef; my $contributor = undef; my $format = "xml"; my $oracle_home = "/share/apps/lib/Oracle/current"; $ENV{ORACLE_HOME} = $oracle_home if ($ENV{ORACLE_HOME} eq ""); $ENV{NLS_LANG} = "american_america.US7ASCII"; $ENV{NLS_DATE_FORMAT} = "yyyy/mm/dd hh24:mi:ss"; # The WSS will always translate URI parameters to command line options # prefixed with a double-dash (--), e.g. 'station=ANMO' becomes '--station ANMO' # # This characteristic is leveraged to allow this handler script to # support options specified with a single dash (for diagnostics and # testing) that can never be specified by a remote call via the WSS. # # This is enforced by limiting the arguments that can be called # using double-dashes to a subset needed to match the web service # request paramters and the special case '--STDIN' and '--username' # options. All such options should be in the @doubledash list. my @doubledash = ('starttime', 'start', 'endtime', 'end', 'minlatitude', 'minlat', 'maxlatitude', 'maxlat', 'minlongitude', 'minlon', 'maxlongitude', 'maxlon', 'latitude', 'lat', 'longitude', 'lon', 'minradius', 'maxradius', 'mindepth', 'maxdepth', 'minmagnitude', 'maxmagnitude', 'minmag', 'maxmag', 'magnitudetype', 'includeallmagnitudes', 'includearrivals', 'includemechanisms', 'eventid', 'limit', 'offset', 'orderby', 'catalog', 'contributor', 'format'); foreach my $idx ( 0..$#ARGV ) { if ( $ARGV[$idx] =~ /^--.+/ ) { my $arg = substr $ARGV[$idx], 2; if ( ! grep (/^${arg}$/, @doubledash) ) { print STDERR "Unrecognized option: $ARGV[$idx]\n"; exit (3); } } } # Parse command line arguments Getopt::Long::Configure (qw{ bundling_override no_auto_abbrev no_ignore_case_always }); my $getoptsret = GetOptions ( 'v+' => \$verbose, 'h' => \$usage, 'p' => \$pretend, 'starttime|start|ts=s' => \$starttime, 'endtime|end|te=s' => \$endtime, 'minlatitude|minlat=s' => \$minlatitude, 'maxlatitude|maxlat=s' => \$maxlatitude, 'minlongitude|minlon=s' => \$minlongitude, 'maxlongitude|maxlon=s' => \$maxlongitude, 'latitude|lat=s' => \$latitude, 'longitude|lon=s' => \$longitude, 'minradius=s' => \$minradius, 'maxradius=s' => \$maxradius, 'mindepth=s' => \$mindepth, 'maxdepth=s' => \$maxdepth, 'minmagnitude|minmag=s' => \$minmagnitude, 'maxmagnitude|maxmag=s' => \$maxmagnitude, 'magnitudetype|magtype=s' => \$magnitudetype, 'includeallmagnitudes=s' => \$includeallmagnitudes, 'includearrivals=s' => \$includearrivals, 'includemechanisms=s' => \$includemechanisms, 'eventid=s' => \$eventid, 'limit=s' => \$limit, 'offset=s' => \$offset, 'orderby=s' => \$orderby, 'catalog=s' => \$catalog, 'contributor=s' => \$contributor, 'format=s' => \$format, ); exit (3) if ( ! $getoptsret ); if ( defined $usage ) { my $name = basename ($0); print STDERR "WSS Handler to fetch event information from the NCEDC ($version)\n\n"; print STDERR "Usage: $name [-v] \n\n"; print STDERR " -h Print this help message\n"; print STDERR " -v Be more verbose, multiple flags can be used\n"; print STDERR " -p Pretend, do everything except request data from backend\n"; print STDERR "\n"; print STDERR " --starttime Specify start time (YYYY-MM-DDTHH:MM:SS[.ssssss])\n"; print STDERR " --endtime Specify end time (YYYY-MM-DDTHH:MM:SS[.ssssss])\n"; print STDERR "\n"; print STDERR " --minlatitude Specify minimum latitude in degrees\n"; print STDERR " --maxlatitude Specify maximum latitude in degrees\n"; print STDERR " --minlongitude Specify minimum longitude in degrees\n"; print STDERR " --maxlongitude Specify maximum longitude in degrees\n"; print STDERR "\n"; print STDERR " --latitude Specify latitude for radius search\n"; print STDERR " --longitude Specify longitude for radius search\n"; print STDERR " --minradius Specify minimum radius from latitude:longitude\n"; print STDERR " --maxradius Specify maximum radius from latitude:longitude\n"; print STDERR "\n"; print STDERR " --mindepth Specify minimum depth\n"; print STDERR " --maxdepth Specify maximum depth\n"; print STDERR " --minmagnitude Specify minimum magnitude\n"; print STDERR " --maxmagnitude Specify maximum magnitude\n"; print STDERR "\n"; print STDERR " --magnitudetype Specify magnitude type\n"; print STDERR "\n"; print STDERR " --includeallmagnitudes Toggle including all magnitudes in results [TRUE|FALSE]\n"; print STDERR " --includearrivals Toggle including phase arrivals in results [TRUE|FALSE]\n"; print STDERR " --includemechanisms Toggle including mechanisms in results [TRUE|FALSE]\n"; print STDERR "\n"; print STDERR " --eventid Specify event identifier\n"; print STDERR " --limit Limit the results to the specified number of events\n"; print STDERR " --offset Return results starting at the event count specified, starting at 1\n"; print STDERR " --orderby Order the results by time or magnitude with the following possibilities:\n"; print STDERR " time: order by origin descending time\n"; print STDERR " time-asc: order by origin ascending time\n"; print STDERR " magnitude: order by descending magnitude\n"; print STDERR " magnitude-asc: order by ascending magnitude\n"; print STDERR " --catalog Specify catalog\n"; print STDERR " --contributor Specify contributor\n"; print STDERR " --format Specify output format [xml|text]\n"; print STDERR "\n"; exit (1); } # Track run duration for diagnostics my $startrequest = time; # Validate global request parameters, exit if needed my $retval = &ValidateRequest(); if ( $retval ) { exit ($retval); } # Handle/fullfill data request my $retval = &HandleRequest(); if ( $retval ) { exit ($retval); } if ( $verbose ) { my $runtime = time - $startrequest; print STDERR "Finished ($runtime seconds)\n"; } # Return with success code exit (0); ## End of main ###################################################################### # HandleRequest: # # Process validated request and return selected data on STDOUT. On # errors this routine should return either an appropriate error code # or exit within the routine with the appropriate message and error # code. The request parameters are available from global variables. # # Name parameter lists: each of $network, $station, $location and # $channel may contain a list of comma separated values, which may # futher contain wildcards. For example, the channel value may # contain "LHE,LHN,LHZ" or "LH?,BH?". # # When a fatal error is reached in this routine be sure to use the # appropriate exit code: # # Exit Status = Description # 1 = General error. An error description may be provided on stderr # 2 = No data. Request was successful but results in no data # 3 = Invalid or unsupported argument/parameter # 4 = Too much data requested # # Returns 0 on success, otherwise an appropriate exit code. ###################################################################### sub HandleRequest () { my $ltime = time(); my $workdir = "/scr/slip/ws.fdsn.ev.$$.$ltime"; my $backendservice = "/share/apps/bin/dbselect"; my $qml_service = "/home/tomcat/local/fdsn-event/qml.pl"; my $text_service = "/home/tomcat/local/fdsn-event/event_text.pl"; my $dbselect_options = " -I"; my $qml_options = " -i - "; # # Time # $starttime =~ s/\-/\//g if ( defined $starttime ); $starttime =~ s/T/,/g if ( defined $starttime ); $starttime =~ s/Z//g if ( defined $starttime ); $endtime =~ s/\-/\//g if ( defined $endtime ); $endtime =~ s/T/,/g if ( defined $endtime ); $endtime =~ s/Z//g if ( defined $endtime ); $dbselect_options .= " -f $starttime" if ( defined $starttime ); $dbselect_options .= " -t $endtime" if ( defined $endtime ); # # Magnitude # my $mim = -1000; my $mam = 1000; $mim = $minmagnitude if ( defined $minmagnitude ); $mam = $maxmagnitude if ( defined $maxmagnitude ); $dbselect_options .= " -m $mim,$mam" if ( defined $minmagnitude || defined $maxmagnitude ); # # Depth # my $mid = -100; my $mad = 1000; $mid = $mindepth if ( defined $mindepth ); $mad = $maxdepth if ( defined $maxdepth ); $dbselect_options .= " -d $mid,$mad" if ( defined $mindepth || defined $maxdepth ); # # Latitude # my $mil = -90; my $mal = 90; $mil = $minlatitude if ( defined $minlatitude ); $mal = $maxlatitude if ( defined $maxlatitude ); $dbselect_options .= " -l $mil,$mal" if ( defined $minlatitude || defined $maxlatitude ); # # Longitude # my $miL = -180; my $maL = 180; $miL = $minlongitude if ( defined $minlongitude ); $maL = $maxlongitude if ( defined $maxlongitude ); $dbselect_options .= " -L $miL,$maL" if ( defined $minlongitude || defined $maxlongitude ); # # Radius # my $rlat = 0; my $rlon = 0; my $rmin = 0; my $rmax = 100; $rlat = $latitude if ( defined $latitude ); $rlon = $longitude if ( defined $longitude ); $rmin = $minradius*111.263 if ( defined $minradius ); $rmax = $maxradius*111.263 if ( defined $maxradius ); $dbselect_options .= " -C $rlat,$rlon,$rmin,$rmax" if ( defined $latitude || defined $longitude || defined $minradius || defined $maxradius ); # # Event Id # $dbselect_options .= " -E $eventid" if ( defined $eventid ); # # Magnitude Type # $dbselect_options .= " -M $magnitudetype" if ( defined $magnitudetype ); # # Catalog # my $cat = "ncss"; $cat = lc($catalog) if ( defined $catalog ); my $dbselect_conf = " -c /home/tomcat/local/fdsn-event/dbselect.conf.$cat "; my $qml_conf = " -c /home/tomcat/local/fdsn-event/qml.conf.$cat "; if ( defined $catalog && lc($catalog) eq "dd" ) { # Catalog is DD $dbselect_options .= " -B "; $qml_options .= " -O D "; } # # Contributor # if ( defined $contributor ) { if ( defined $catalog ) { if ( lc($catalog) eq "egs" ) { # Catalog is EGS $dbselect_options .= " -U $contributor"; } else { # Catalog is NCSS or DD if ( lc($contributor) ne "nc" ) { $dbselect_options .= " -U $contributor"; } } } else { # Catalog is NCSS if ( lc($contributor) ne "nc" ) { $dbselect_options .= " -U $contributor"; } } } # # Order by # my $sort_options = " -r -k1,2 "; if ( defined $orderby ) { if ( $orderby eq "time" ) { $sort_options = " -r -k1,2 "; } elsif ( $orderby eq "time-asc" ) { $sort_options = " -k1,2 "; } elsif ( $orderby eq "magnitude" ) { if ( $format eq "text" ) { $sort_options = " -r -k16,16 "; } else { $sort_options = " -r -k6,6 "; } } elsif ( $orderby eq "magnitude-asc" ) { if ( $format eq "text" ) { $sort_options = " -k16,16 "; } else { $sort_options = " -k6,6 "; } } } # # Limit # my $awk_limit = 10000; $awk_limit = $limit if ( defined $limit ); # # Offset # my $awk_offset = 1; $awk_offset = $offset if ( defined $offset ); # # Include all magnitudes & arrivals # $qml_options .= " -M " if ( lc($includeallmagnitudes) eq "true" ); $qml_options .= " -S " if ( lc($includearrivals) eq "true" ); $qml_options .= " -A " if ( lc($includemechanisms) eq "true" ); # # Run backend service # my $awk_cmd = undef; my $cmd = undef; if ($format eq "xml") { $awk_cmd = "awk 'NR >= $awk_offset && NR < $awk_offset+$awk_limit {print \$13;}'"; $cmd = "$backendservice $dbselect_conf $dbselect_options | sort $sort_options | $awk_cmd | $qml_service $qml_conf $qml_options > $workdir/fdsn.ev.$$"; } else { $awk_cmd = "awk 'NR >= $awk_offset && NR < $awk_offset+$awk_limit {print \$0;}'"; $cmd = "$backendservice $dbselect_conf -F detail -Q $dbselect_options | sort $sort_options | $awk_cmd | $text_service > $workdir/fdsn.ev.$$"; } if ( $verbose >= 1 ) { print STDERR "Backend Call:\n$cmd\n"; } # Stop here if pretending return 0 if $pretend; # Create working directory system ("mkdir $workdir"); # Call back end service system ($cmd); # Test if QuakeMl file contains data if (-s "$workdir/fdsn.ev.$$" < 12) { # Remove working directory $cmd = "rm -rf $workdir"; system ($cmd); print STDERR "No Data Found\n"; return 2; } # Returns output file $cmd = "cat $workdir/fdsn.ev.$$"; system ($cmd); # Remove working directory $cmd = "rm -rf $workdir"; system ($cmd); return 0; } # End of HandleRequest() ###################################################################### # ValidateRequest: # # Validate the data selection parameter values and print specific # errors to STDERR. # # Expected date-time formats are one of: # # YYYY-MM-DD[T]HH:MM:SS.ssssss # YYYY-MM-DD[T]HH:MM:SS # # Month, day, hour, min and second values may be single digits. # # If specified, network, station, location and channel are # validated for length and characters allowed in the SEED 2.4 # specification or wildcards. # # Name parameter lists: each of network, station, location and channel # may contain a list of comma separated values, which may futher # contain wildcards. For example, the channel value may contain # "LHE,LHN,LHZ" or "LH?,BH?". # # Returns 0 on success, otherwise an appropriate exit code. ###################################################################### sub ValidateRequest () { my $retval = 0; if ( $starttime && ! ValidDateTime ($starttime) ) { print STDERR "Unrecognized start time [YYYY-MM-DDTHH:MM:SS[.ssssss]]: '$starttime'\n"; $retval = 3; } if ( $endtime && ! ValidDateTime ($endtime) ) { print STDERR "Unrecognized end time [YYYY-MM-DDTHH:MM:SS[.ssssss]]: '$endtime'\n"; $retval = 3; } if ( $starttime && $endtime ) { # Check for impossible time windows my $startepoch = str2time ($starttime, "UTC"); my $endepoch = str2time ($endtime, "UTC"); if ( $startepoch > $endepoch ) { print STDERR "Start time must be before end time, start: '$starttime', end: '$endtime'\n"; $retval = 3; } } # Validate minlatitude option, must be a decimal value between -90 and 90 if ( defined $minlatitude ) { if ( $minlatitude !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for minlatitude [decimal degrees]: '$minlatitude'\n"; $retval = 3; } elsif ( $minlatitude < -90.0 || $minlatitude > 90.0 ) { print STDERR "Value for minlatitude out of range [-90 to 90]: '$minlatitude'\n"; $retval = 3; } } # Validate maxlatitude option, must be a decimal value between -90 and 90 if ( defined $maxlatitude ) { if ( $maxlatitude !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for maxlatitude [decimal degrees]: '$maxlatitude'\n"; $retval = 3; } elsif ( $maxlatitude < -90.0 || $maxlatitude > 90.0 ) { print STDERR "Value for maxlatitude out of range [-90 to 90]: '$maxlatitude'\n"; $retval = 3; } } # Test latitude interval if ( defined $minlatitude && defined $maxlatitude ) { if ( $minlatitude > $maxlatitude ) { print STDERR "Minimum latitude is greater than maximum latitude: '$minlatitude','$maxlatitude'\n"; $retval = 3; } } # Validate minlongitude option, must be a decimal value between -180 and 180 if ( defined $minlongitude ) { if ( $minlongitude !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for minlongitude [decimal degrees]: '$minlongitude'\n"; $retval = 3; } elsif ( $minlongitude < -180.0 || $minlongitude > 180.0 ) { print STDERR "Value for minlongitude out of range [-180 to 180]: '$minlongitude'\n"; $retval = 3; } } # Validate maxlongitude option, must be a decimal value between -180 and 180 if ( defined $maxlongitude ) { if ( $maxlongitude !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for maxlongitude [decimal degrees]: '$maxlongitude'\n"; $retval = 3; } elsif ( $maxlongitude < -180.0 || $maxlongitude > 180.0 ) { print STDERR "Value for maxlongitude out of range [-180 to 180]: '$maxlongitude'\n"; $retval = 3; } } # Test longitude interval if ( defined $minlongitude && defined $maxlongitude ) { if ( $minlongitude > $maxlongitude ) { print STDERR "Minimum longitude is greater than maximum longitude: '$minlongitude','$maxlongitude'\n"; $retval = 3; } } # Validate latitude option, must be a decimal value between -90 and 90 if ( defined $latitude ) { if ( $latitude !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for latitude [decimal degrees]: '$latitude'\n"; $retval = 3; } elsif ( $latitude < -90.0 || $latitude > 90.0 ) { print STDERR "Value for latitude out of range [-90 to 90]: '$latitude'\n"; $retval = 3; } } # Validate longitude option, must be a decimal value between -180 and 180 if ( defined $longitude ) { if ( $longitude !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for longitude [decimal degrees]: '$longitude'\n"; $retval = 3; } elsif ( $longitude < -180.0 || $longitude > 180.0 ) { print STDERR "Value for longitude out of range [-180 to 180]: '$longitude'\n"; $retval = 3; } } # Validate minradius option, must be a decimal value between 0 and 180 if ( defined $minradius ) { if ( $minradius !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for minradius [decimal degrees]: '$minradius'\n"; $retval = 3; } elsif ( $minradius < 0.0 || $minradius > 180.0 ) { print STDERR "Value for minradius out of range [0 to 180]: '$minradius'\n"; $retval = 3; } } # Validate maxradius option, must be a decimal value between 0 and 180 if ( defined $maxradius ) { if ( $maxradius !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for maxradius [decimal degrees]: '$maxradius'\n"; $retval = 3; } elsif ( $maxradius < 0.0 || $maxradius > 180.0 ) { print STDERR "Value for maxradius out of range [0 to 180]: '$maxradius'\n"; $retval = 3; } } # Check that latitude & longitude are specified if minradius or maxradius is specified if ( (defined $minradius || defined $maxradius) && ! (defined $latitude && defined $longitude) ) { print STDERR "latitude and longitude must be specified if minradius and/or maxradius is used\n"; $retval = 3; } # Check that min/max lat/lon is not combined with lat/lon/radius if ( (defined $minlatitude || defined $maxlatitude || defined $minlongitude || defined $maxlongitude) && (defined $minradius || defined $maxradius) ) { print STDERR "[min|max]latitude and [min|max]longitude cannot be combined with latitude, longitude [min|max]radius\n"; $retval = 3; } # Test radius interval if ( defined $minradius && defined $maxradius ) { if ( $minradius > $maxradius ) { print STDERR "Minimum radius is greater than maximum radius: '$minradius','$maxradius'\n"; $retval = 3; } } # Validate includeallmagnitudes option, must be TRUE or FALSE case insensitive if ( $includeallmagnitudes && ($includeallmagnitudes !~ /^TRUE$/i && $includeallmagnitudes !~ /^FALSE$/i) ) { print STDERR "Unrecognized value for includeallmagnitudes [TRUE or FALSE]: '$includeallmagnitudes'\n"; $retval = 3; } # Validate includearrivals option, must be TRUE or FALSE case insensitive if ( $includearrivals && ($includearrivals !~ /^TRUE$/i && $includearrivals !~ /^FALSE$/i) ) { print STDERR "Unrecognized value for includearrivals [TRUE or FALSE]: '$includearrivals'\n"; $retval = 3; } # Validate includemechanisms option, must be TRUE or FALSE case insensitive if ( $includemechanisms && ($includemechanisms !~ /^TRUE$/i && $includemechanisms !~ /^FALSE$/i) ) { print STDERR "Unrecognized value for includemechanisms [TRUE or FALSE]: '$includemechanisms'\n"; $retval = 3; } # Validate mindepth option, must be a decimal value if ( defined $mindepth ) { if ( $mindepth !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for mindepth [kilometers]: '$mindepth'\n"; $retval = 3; } } # Validate maxdepth option, must be a decimal value if ( defined $maxdepth ) { if ( $maxdepth !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for maxdepth [kilometers]: '$maxdepth'\n"; $retval = 3; } } # Test depth interval if ( defined $mindepth && defined $maxdepth ) { if ( $mindepth > $maxdepth ) { print STDERR "Minimum depth is greater than maximum depth: '$mindepth','$maxdepth'\n"; $retval = 3; } } # Validate minmagnitude option, must be a decimal value if ( defined $minmagnitude ) { if ( $minmagnitude !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for minmagnitude: '$minmagnitude'\n"; $retval = 3; } } # Validate maxmagnitude option, must be a decimal value if ( defined $maxmagnitude ) { if ( $maxmagnitude !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for maxmagnitude: '$maxmagnitude'\n"; $retval = 3; } } # Test magnitude interval if ( defined $minmagnitude && defined $maxmagnitude ) { if ( $minmagnitude > $maxmagnitude ) { print STDERR "Minimum magnitude is greater than maximum magnitude: '$minmagnitude','$maxmagnitude'\n"; $retval = 3; } } # Validate limit option, must be a decimal value >= 0 if ( defined $limit ) { if ( $limit !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for limit: '$limit'\n"; $retval = 3; } elsif ( $limit < 0 ) { print STDERR "Value for limit out of range [>= 0]: '$limit'\n"; $retval = 3; } } # Validate offset option, must be a decimal value >= 1 if ( defined $offset ) { if ( $offset !~ /^[+-]?\d+(\.\d+)?$/ ) { print STDERR "Unrecognized value for offset: '$offset'\n"; $retval = 3; } elsif ( $offset < 1 ) { print STDERR "Value for offset out of range [>= 1]: '$offset'\n"; $retval = 3; } } # Validate catalog option, must be "ncss" or "egs" if ( $catalog && $catalog !~ /^(ncss|egs|dd)$/i ) { print STDERR "Unrecognized catalog selection [ncss, egs, dd]: '$catalog'\n"; $retval = 3; } # Validate orderby option, must be "time", "time-asc", "magnitude" or "magnitude-asc" if ( $orderby && $orderby !~ /^(time|time-asc|magnitude|magnitude-asc)$/i ) { print STDERR "Unrecognized orderby selection [time, time-asc, magnitude, magnitude-asc]: '$orderby'\n"; $retval = 3; } return $retval; } # End of ValidateRequest() ###################################################################### # ValidateDateTime: # # Validate a string to match one of these date-time formats: # # YYYY-MM-DD[T]HH:MM:SS.ssssss # YYYY-MM-DD[T]HH:MM:SS # # Returns 1 on match and 0 on non-match. ###################################################################### sub ValidDateTime () { my $string = shift; return 0 if ( ! $string ); return 1 if ( $string =~ /^\d{4}-[01]\d-[0-3]\d[T][0-2]\d:[0-5]\d:[0-5]\d\.\d+(Z)?$/ || $string =~ /^\d{4}-[01]\d-[0-3]\d[T][0-2]\d:[0-5]\d:[0-5]\d(Z)?$/ ); return 0; } # End of ValidDateTime