Changeset 28


Ignore:
Timestamp:
Oct 12, 2006, 8:28:10 PM (13 years ago)
Author:
Dominic Hargreaves
Message:

submit is now a FastCGI application

File:
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/npemap.org.uk/cgi/submit.fcgi

    r27 r28  
    55
    66use DBI;
    7 use CGI qw/:standard -debug/;
     7use CGI::Fast qw/:standard -debug/;
    88use Geo::Postcode;
    99use Date::Format;
     
    1111sub print_err;
    1212sub print_ok;
     13sub setup_dbh;
    1314
    14 my $dbh = DBI->connect("dbi:Pg:dbname=npemaps","npemaps","") or
    15     print_err("Could not connect to database");
     15# Set up database handler to try and make sure it's ready for the first
     16# request
     17# No point in handling errors here since they'll get handled by the request
     18# handler
     19my $dbh;
     20setup_dbh();
    1621
    17 my $cgi = new CGI;
    1822
    19 my ($easting, $northing);
    2023my @fields = qw(easting northing postcode);
    2124
    22 # Input validation
    23 foreach my $field (@fields) {
    24     unless (defined $cgi->param($field)) {
    25         print_err ("Parameter '$field' missing");
     25my $cgi;
     26# Process incoming requests
     27REQUEST: while ($cgi = new CGI::Fast) {
     28
     29    # In case the database went away, make sure we have a connection
     30    unless (setup_dbh()) {
     31        print_err('Error setting up database connection');
     32        next REQUEST;
     33    }
     34
     35    my ($easting, $northing);
     36
     37    # Input validation
     38    foreach my $field (@fields) {
     39        unless (defined $cgi->param($field)) {
     40            print_err ("Parameter '$field' missing");
     41            next REQUEST;
     42        }
     43    }
     44
     45    # Is the Easting in a valid range?
     46    if (($cgi->param('easting') > 700000) or
     47        ($cgi->param('easting') < 0)) {
     48        print_err ("Parameter 'easting' must be an integer between 0 and 700,000");
     49        next REQUEST;
     50    } else {
     51        $easting = $cgi->param('easting');
     52    }
     53
     54    # Is the Northing in a valid range?
     55    if (($cgi->param('northing') > 1300000) or
     56        ($cgi->param('northing') < 0)) {
     57        print_err("Parameter 'northing' must be an integer between 0 and 1,300,000");
     58        next REQUEST;
     59    } else {
     60        $northing = $cgi->param('northing');
     61    }
     62
     63    my $sth;
     64
     65    # Now validate the postcode input format
     66    my $raw_postcode = $cgi->param('postcode');
     67    my $postcode = Geo::Postcode->new($raw_postcode);
     68    my ($first, $second, $third, $fourth) = @{$postcode->fragments};
     69    my ($outward, $inward);
     70
     71    if ($postcode->valid) {
     72        # We have a complete postcode; input it straight into the database
     73        $outward = $first . $second;
     74        $inward = $third . $fourth;
     75    } elsif($postcode->valid_fragment) {
     76        # We have a valid fragment; let's build up what we can
     77        # We are guaranteed to have the first two
     78        $outward = $first . $second;
     79        $inward = $third if $third;
     80        $inward .= $fourth if $fourth;
     81    } else {
     82        print_err("The postcode format is not valid");
     83        next REQUEST;
     84    }
     85
     86    # Check for a duplicate.
     87    # We want to collect duplicates from different IP addresses as a kind of
     88    # corroboration factor; this just catches accidental double-submission
     89    # really.
     90    $sth = $dbh->prepare('SELECT * FROM postcodes WHERE raw_postcode = ? AND easting = ? AND northing = ? AND ip = ?');
     91    unless ($sth->execute($raw_postcode, $easting, $northing, $ENV{'REMOTE_ADDR'})) {
     92        print_err('Database error when checking for duplicate data :(');
     93        next REQUEST;
     94    }
     95
     96    if ($sth->rows) {
     97        print_err('You, or someone with the same IP address, have already submitted this postcode with these co-ordinates.');
     98        next REQUEST;
     99    }
     100
     101    $sth = $dbh->prepare('INSERT INTO postcodes (outward, inward, raw_postcode, easting, northing, ip, created_at, source) VALUES (?, ?, ?, ?, ?, ?, ?, 0)');
     102    if ($sth->execute($outward, $inward, $raw_postcode, $easting, $northing, $ENV{'REMOTE_ADDR'}, time2str('%Y-%m-%d %H:%M:%S', time))) {
     103        print "Content-type: text/html\n\n";
     104        print "<html><head><title>Thank you</title></head>\n";
     105        print "<body>Thank you for telling us where your post code is!\n";
     106        print "</body></html>";
     107        next REQUEST;
     108    } else {
     109        print STDERR "DB error: " . $dbh->errstr . "\n";
     110        print_err("Database error when adding your data :(");
     111        next REQUEST;
    26112    }
    27113}
    28114
    29 # Is the Easting in a valid range?
    30 if (($cgi->param('easting') > 700000) or
    31     ($cgi->param('easting') < 0)) {
    32     print_err ("Parameter 'easting' must be an integer between 0 and 700,000");
    33 } else {
    34     $easting = $cgi->param('easting');
    35 }
     115# No more requests to serve, so tidy up
     116$dbh->disconnect;
    36117
    37 # Is the Northing in a valid range?
    38 if (($cgi->param('northing') > 1300000) or
    39     ($cgi->param('northing') < 0)) {
    40     print_err("Parameter 'northing' must be an integer between 0 and 1,300,000");
    41 } else {
    42     $northing = $cgi->param('northing');
    43 }
    44 
    45 my $sth;
    46 
    47 # Now validate the postcode input format
    48 my $raw_postcode = $cgi->param('postcode');
    49 my $postcode = Geo::Postcode->new($raw_postcode);
    50 my ($first, $second, $third, $fourth) = @{$postcode->fragments};
    51 my ($outward, $inward);
    52 
    53 if ($postcode->valid) {
    54     # We have a complete postcode; input it straight into the database
    55     $outward = $first . $second;
    56     $inward = $third . $fourth;
    57 } elsif($postcode->valid_fragment) {
    58     # We have a valid fragment; let's build up what we can
    59     # We are guaranteed to have the first two
    60     $outward = $first . $second;
    61     $inward = $third if $third;
    62     $inward .= $fourth if $fourth;
    63 } else {
    64     print_err("The postcode format is not valid");
    65 }
    66 
    67 # Check for a duplicate.
    68 # We want to collect duplicates from different IP addresses as a kind of
    69 # corroboration factor; this just catches accidental double-submission
    70 # really.
    71 $sth = $dbh->prepare('SELECT * FROM postcodes WHERE raw_postcode = ? AND easting = ? AND northing = ? AND ip = ?');
    72 unless ($sth->execute($raw_postcode, $easting, $northing, $ENV{'REMOTE_ADDR'})) {
    73     print_err('Database error when checking for duplicate data :(');
    74 }
    75 
    76 if ($sth->rows) {
    77     print_err('You, or someone with the same IP address, have already submitted this postcode with these co-ordinates.');
    78 }
    79 
    80 $sth = $dbh->prepare('INSERT INTO postcodes (outward, inward, raw_postcode, easting, northing, ip, created_at, source) VALUES (?, ?, ?, ?, ?, ?, ?, 0)');
    81 if ($sth->execute($outward, $inward, $raw_postcode, $easting, $northing, $ENV{'REMOTE_ADDR'}, time2str('%Y-%m-%d %H:%M:%S', time))) {
    82     print "Content-type: text/html\n\n";
    83     print "<html><head><title>Thank you</title></head>\n";
    84     print "<body>Thank you for telling us where your post code is!\n";
    85     print "</body></html>";
    86     exit 0;
    87 } else {
    88     print STDERR "DB error: " . $dbh->errstr . "\n";
    89     print_err("Database error when adding your data :(");
    90 }
    91 
    92 sub print_err ($) {
     118# Helper routines
     119sub print_err($) {
    93120    my $err = shift;
    94121    print "Content-type: text/html\n\n";
     
    102129    }
    103130    print "</ul></body></html>\n";
    104     exit 0;
    105131}
     132
     133sub setup_dbh {
     134    # $dbh is global
     135    return $dbh = DBI->connect_cached("dbi:Pg:dbname=npemaps","npemaps","");
     136}
Note: See TracChangeset for help on using the changeset viewer.