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

Last change on this file since 261 was 261, checked in by Dominic Hargreaves, 14 years ago

Try to record the user agent.

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