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

Last change on this file since 566 was 566, checked in by Nick Burch, 13 years ago

Handle negative northings

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