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

Last change on this file was 635, checked in by Dominic Hargreaves, 12 years ago

licence tastic

  • Property svn:executable set to *
File size: 6.3 KB
Line 
1#!/usr/bin/perl
2#
3# Copyright (c) 2006 Dominic Hargreaves
4# Permission is hereby granted, free of charge, to any person obtaining a
5# copy of this software and associated documentation files (the "Software"),
6# to deal in the Software without restriction, including without limitation
7# the rights to use, copy, modify, merge, publish, distribute, sublicense,
8# and/or sell copies of the Software, and to permit persons to whom the
9# Software is furnished to do so, subject to the following conditions:
10#
11# The above copyright notice and this permission notice shall be included in
12# all copies or substantial portions of the Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20# IN THE SOFTWARE.
21#
22use strict;
23use warnings;
24
25use CGI::Fast qw/:standard -debug/;
26use Geo::Postcode;
27
28# Find our private perl libraries
29use FindBin;
30use lib "$FindBin::Bin/../perllib";
31use NPEMap;
32use NPEMap::Postcodes;
33
34# Set up database handler to try and make sure it's ready for the first
35# request
36# No point in handling errors here since they'll get handled by the request
37# handler
38my $dbh = setup_dbh();
39
40my @fields = qw(easting northing postcode1 postcode2);
41my $returnBaseURL = '';
42
43my $googleAnalytics = <<"HERE";
44<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
45</script>
46<script type="text/javascript">
47_uacct = "UA-732621-2";
48if (typeof urchinTracker == 'function') urchinTracker();
49</script>
50HERE
51my $cgi;
52# Process incoming requests
53REQUEST: while ($cgi = new CGI::Fast) {
54
55my $returnlink = '';
56   
57
58
59    # In case the database went away, make sure we have a connection
60    unless ($dbh = setup_dbh()) {
61        print_html_err('Error setting up database connection', $returnlink);
62        next REQUEST;
63    }
64
65    my ($easting, $northing);
66
67    # Input validation
68    foreach my $field (@fields) {
69        unless (defined $cgi->param($field)) {
70            print_html_err ("Parameter '$field' missing", $returnlink);
71            next REQUEST;
72        }
73    }
74
75    # Is the Easting in a valid range?
76    if (($cgi->param('easting') > 700000) or
77        ($cgi->param('easting') < 0)) {
78        print_html_err ("Parameter 'easting' must be an integer between 0 and 700,000", $returnlink);
79        next REQUEST;
80    } else {
81        $easting = $cgi->param('easting');
82    }
83
84    # Is the Northing in a valid range?
85        # (Channel islands stop at -87,000)
86    if (($cgi->param('northing') > 1300000) or
87                ($cgi->param('northing') < -87000)) {
88                print_err("Parameter 'northing' must be an integer between -87,000 and 1,300,000");
89        next REQUEST;
90    } else {
91        $northing = $cgi->param('northing');
92    }
93
94        # Are they using the irish grid?
95        my $ie = 0;
96        if(defined $cgi->param('ie')) {
97                $ie = 1;
98        }
99        if(defined $cgi->param('grid') && ($cgi->param('grid') eq 'osie')) {
100                $ie = 1;
101        }
102
103        # What column do we use for the postcode?
104        my $easting_col = "easting";
105        my $northing_col = "northing";
106        if($ie) {
107                $easting_col = "ie_easting";
108                $northing_col = "ie_northing";
109        }
110
111    my $sth;
112
113    # Now validate the postcode input format
114    my ($trimmed_1, $trimmed_2) = ($cgi->param('postcode1'), $cgi->param('postcode2'));
115    $trimmed_1 =~ s/^\s+//;
116    $trimmed_2 =~ s/^\s+//;
117    $trimmed_1 =~ s/\s+$//;
118    $trimmed_2 =~ s/\s+$//;
119    my $raw_postcode = $trimmed_1;
120    $raw_postcode .= ' ' . $trimmed_2 if defined $trimmed_2;
121
122    unless ((length($trimmed_2)) == 1 or (length($trimmed_2) == 0) or (length($trimmed_2) == 3) or (!defined $trimmed_2)) {
123        print_html_err("The postcode format is not valid", $returnlink);
124        next REQUEST;
125    }
126
127    my $postcode = Geo::Postcode->new($raw_postcode);
128    my ($first, $second, $third, $fourth) = @{$postcode->fragments};
129    my ($outward, $inward);
130
131    if ($postcode->valid) {
132        # We have a complete postcode; input it straight into the database
133        $outward = $first . $second;
134        $inward = $third . $fourth;
135    } elsif($postcode->valid_fragment) {
136        # We have a valid fragment; let's build up what we can
137        # We are guaranteed to have the first two
138        $outward = $first . $second;
139        $inward = '';
140        $inward .= $third if defined $third;
141        $inward .= $fourth if defined $fourth;
142    } else {
143        print_html_err("The postcode format is not valid", $returnlink);
144        next REQUEST;
145    }
146
147    # Check for a duplicate.
148    # We want to collect duplicates from different IP addresses as a kind of
149    # corroboration factor; this just catches accidental double-submission
150    # really.
151    $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");
152    unless ($sth->execute($cgi->param('postcode1'), $cgi->param('postcode2'), $easting, $northing, $ENV{'REMOTE_ADDR'})) {
153        print_html_err('Database error when checking for duplicate data :(', $returnlink);
154        next REQUEST;
155    }
156
157    if ($sth->rows) {
158        print_html_err('You, or someone with the same IP address, have already submitted this postcode with these co-ordinates.', $returnlink);
159        next REQUEST;
160    }
161
162    $sth = $dbh->prepare("INSERT INTO postcodes (outward, inward, raw_postcode_outward, raw_postcode_inward, $easting_col, $northing_col, ip, source, user_agent) VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?)");
163    if ($sth->execute($outward, $inward, $cgi->param('postcode1'), $cgi->param('postcode2'), $easting, $northing, $ENV{'REMOTE_ADDR'}, $ENV{'HTTP_USER_AGENT'})) {
164        print "Content-type: text/html\n\n";
165        print "<p>Thank you for telling us where your post code is!</p>\n";
166        # Any extra actions
167        build_home_stats($dbh);
168        next REQUEST;
169    } else {
170        print STDERR "DB error: " . $dbh->errstr . "\n";
171        print_html_err("Database error when adding your data :(", $returnlink);
172        next REQUEST;
173    }
174
175# WE NEVER GET HERE
176
177}
178
179# No more requests to serve, so tidy up
180$dbh->disconnect;
Note: See TracBrowser for help on using the repository browser.