source: trunk/npemap.org.uk/cgi/submit.fcgi @ 249

Last change on this file since 249 was 238, checked in by Dominic Hargreaves, 15 years ago

Make CGIs use shared error functions.

  • Property svn:executable set to *
File size: 5.3 KB
RevLine 
[13]1#!/usr/bin/perl
[81]2#
[82]3# Copyright (c) 2006 Dominic Hargreaves
[81]4# See accompanying file "LICENCE" for licence details
[13]5
6use strict;
7use warnings;
8
9use DBI;
[28]10use CGI::Fast qw/:standard -debug/;
[13]11use Geo::Postcode;
12
[222]13# Find our private perl libraries
14use FindBin;
15use lib "$FindBin::Bin/../perllib";
16use NPEMap;
[227]17use NPEMap::Postcodes;
[222]18
[28]19# Set up database handler to try and make sure it's ready for the first
20# request
21# No point in handling errors here since they'll get handled by the request
22# handler
[222]23my $dbh = setup_dbh();
[13]24
[72]25my @fields = qw(easting northing postcode1 postcode2);
[71]26my $returnBaseURL = '';
[13]27
[28]28my $cgi;
29# Process incoming requests
30REQUEST: while ($cgi = new CGI::Fast) {
31
[40]32    # If we're given return URL parameters, basic sanity check to stop
33    # funny business
[41]34   
[71]35    my $returnlink = '<a href="' . $returnBaseURL . '/tiles/map.html">Go back to the map</a>';   
[40]36
[71]37    if (defined $cgi->param('easting') and ($cgi->param('easting') =~ /\d+/) and
38        defined $cgi->param('northing') and ($cgi->param('northing') =~ /\d+/) ) {
[130]39        $returnlink = '<a href="' . $returnBaseURL . '/tiles/map.html#' . int($cgi->param('easting')/1000). ",".int($cgi->param('northing')/1000)  . ',1">Go back to the map</a>';
[40]40    }
41
42
[28]43    # In case the database went away, make sure we have a connection
[222]44    unless ($dbh = setup_dbh()) {
[238]45        print_html_err('Error setting up database connection', $returnlink);
[28]46        next REQUEST;
[13]47    }
48
[28]49    my ($easting, $northing);
[13]50
[28]51    # Input validation
52    foreach my $field (@fields) {
53        unless (defined $cgi->param($field)) {
[238]54            print_html_err ("Parameter '$field' missing", $returnlink);
[28]55            next REQUEST;
56        }
57    }
[13]58
[28]59    # Is the Easting in a valid range?
60    if (($cgi->param('easting') > 700000) or
61        ($cgi->param('easting') < 0)) {
[238]62        print_html_err ("Parameter 'easting' must be an integer between 0 and 700,000", $returnlink);
[28]63        next REQUEST;
64    } else {
65        $easting = $cgi->param('easting');
66    }
[13]67
[28]68    # Is the Northing in a valid range?
69    if (($cgi->param('northing') > 1300000) or
70        ($cgi->param('northing') < 0)) {
[238]71        print_html_err("Parameter 'northing' must be an integer between 0 and 1,300,000", $returnlink);
[28]72        next REQUEST;
73    } else {
74        $northing = $cgi->param('northing');
75    }
[13]76
[28]77    my $sth;
[13]78
[28]79    # Now validate the postcode input format
[139]80    my ($trimmed_1, $trimmed_2) = ($cgi->param('postcode1'), $cgi->param('postcode2'));
81    $trimmed_1 =~ s/^\s+//;
82    $trimmed_2 =~ s/^\s+//;
83    $trimmed_1 =~ s/\s+$//;
84    $trimmed_2 =~ s/\s+$//;
85    my $raw_postcode = $trimmed_1;
86    $raw_postcode .= ' ' . $trimmed_2 if defined $trimmed_2;
87
[140]88    unless ((length($trimmed_2)) == 1 or (length($trimmed_2) == 0) or (length($trimmed_2) == 3) or (!defined $trimmed_2)) {
[238]89        print_html_err("The postcode format is not valid", $returnlink);
[139]90        next REQUEST;
91    }
92
93    my $postcode = Geo::Postcode->new($raw_postcode);
[28]94    my ($first, $second, $third, $fourth) = @{$postcode->fragments};
95    my ($outward, $inward);
[27]96
[28]97    if ($postcode->valid) {
98        # We have a complete postcode; input it straight into the database
99        $outward = $first . $second;
100        $inward = $third . $fourth;
101    } elsif($postcode->valid_fragment) {
102        # We have a valid fragment; let's build up what we can
103        # We are guaranteed to have the first two
104        $outward = $first . $second;
[37]105        $inward = '';
[44]106        $inward .= $third if defined $third;
107        $inward .= $fourth if defined $fourth;
[28]108    } else {
[238]109        print_html_err("The postcode format is not valid", $returnlink);
[28]110        next REQUEST;
111    }
[27]112
[28]113    # Check for a duplicate.
114    # We want to collect duplicates from different IP addresses as a kind of
115    # corroboration factor; this just catches accidental double-submission
116    # really.
[169]117    $sth = $dbh->prepare('SELECT raw_postcode_outward FROM postcodes WHERE raw_postcode_outward = ? AND raw_postcode_inward = ? AND easting = ? AND northing = ? AND ip = ? AND NOT deleted');
[72]118    unless ($sth->execute($cgi->param('postcode1'), $cgi->param('postcode2'), $easting, $northing, $ENV{'REMOTE_ADDR'})) {
[238]119        print_html_err('Database error when checking for duplicate data :(', $returnlink);
[28]120        next REQUEST;
121    }
122
123    if ($sth->rows) {
[238]124        print_html_err('You, or someone with the same IP address, have already submitted this postcode with these co-ordinates.', $returnlink);
[28]125        next REQUEST;
126    }
127
[72]128    $sth = $dbh->prepare('INSERT INTO postcodes (outward, inward, raw_postcode_outward, raw_postcode_inward, easting, northing, ip, source) VALUES (?, ?, ?, ?, ?, ?, ?, 0)');
129    if ($sth->execute($outward, $inward, $cgi->param('postcode1'), $cgi->param('postcode2'), $easting, $northing, $ENV{'REMOTE_ADDR'})) {
[28]130        print "Content-type: text/html\n\n";
131        print "<html><head><title>Thank you</title></head>\n";
[40]132        print "<body><p>Thank you for telling us where your post code is!</p>\n";
133        print "<p>$returnlink</p>\n";
[28]134        print "</body></html>";
[234]135        # Any extra actions
136        build_home_stats($dbh);
[28]137        next REQUEST;
138    } else {
139        print STDERR "DB error: " . $dbh->errstr . "\n";
[238]140        print_html_err("Database error when adding your data :(", $returnlink);
[28]141        next REQUEST;
142    }
[227]143
[234]144# WE NEVER GET HERE
[227]145
[13]146}
147
[28]148# No more requests to serve, so tidy up
149$dbh->disconnect;
Note: See TracBrowser for help on using the repository browser.