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

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

Store an empty string in inward rather than NULL (allows concatenation later)

  • Property svn:executable set to *
File size: 4.3 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use DBI;
7use CGI::Fast qw/:standard -debug/;
8use Geo::Postcode;
9use Date::Format;
10
11sub print_err;
12sub print_ok;
13sub setup_dbh;
14
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();
21
22
23my @fields = qw(easting northing postcode);
24
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 = '';
80        $inward .= $third if $third;
81        $inward .= $fourth if $fourth;
82    } else {
83        print_err("The postcode format is not valid");
84        next REQUEST;
85    }
86
87    # Check for a duplicate.
88    # We want to collect duplicates from different IP addresses as a kind of
89    # corroboration factor; this just catches accidental double-submission
90    # really.
91    $sth = $dbh->prepare('SELECT raw_postcode FROM postcodes WHERE raw_postcode = ? AND easting = ? AND northing = ? AND ip = ?');
92    unless ($sth->execute($raw_postcode, $easting, $northing, $ENV{'REMOTE_ADDR'})) {
93        print_err('Database error when checking for duplicate data :(');
94        next REQUEST;
95    }
96
97    if ($sth->rows) {
98        print_err('You, or someone with the same IP address, have already submitted this postcode with these co-ordinates.');
99        next REQUEST;
100    }
101
102    $sth = $dbh->prepare('INSERT INTO postcodes (outward, inward, raw_postcode, easting, northing, ip, created_at, source) VALUES (?, ?, ?, ?, ?, ?, ?, 0)');
103    if ($sth->execute($outward, $inward, $raw_postcode, $easting, $northing, $ENV{'REMOTE_ADDR'}, time2str('%Y-%m-%d %H:%M:%S', time))) {
104        print "Content-type: text/html\n\n";
105        print "<html><head><title>Thank you</title></head>\n";
106        print "<body>Thank you for telling us where your post code is!\n";
107        print "</body></html>";
108        next REQUEST;
109    } else {
110        print STDERR "DB error: " . $dbh->errstr . "\n";
111        print_err("Database error when adding your data :(");
112        next REQUEST;
113    }
114}
115
116# No more requests to serve, so tidy up
117$dbh->disconnect;
118
119# Helper routines
120sub print_err($) {
121    my $err = shift;
122    print "Content-type: text/html\n\n";
123    print "<html><head><title>Error submitting</title></head>\n";
124    print "<body><p>The following error occurred whilst submitting data:\n";
125    print CGI::escapeHTML($err);
126    print "</p><p>Your input was:</p>\n<ul>";
127    foreach my $field (@fields) {
128        my $param = $cgi->param($field) || '';
129        print "<li>$field: " . $param . "</li>\n";
130    }
131    print "</ul></body></html>\n";
132}
133
134sub setup_dbh {
135    # $dbh is global
136    return $dbh = DBI->connect_cached("dbi:Pg:dbname=npemaps","npemaps","");
137}
Note: See TracBrowser for help on using the repository browser.