aboutsummaryrefslogtreecommitdiffstats
path: root/web/index.cgi
diff options
context:
space:
mode:
Diffstat (limited to 'web/index.cgi')
-rwxr-xr-xweb/index.cgi235
1 files changed, 157 insertions, 78 deletions
diff --git a/web/index.cgi b/web/index.cgi
index e503f50ba..62a882e6b 100755
--- a/web/index.cgi
+++ b/web/index.cgi
@@ -16,6 +16,8 @@ use RABX;
use CGI::Carp;
use URI::Escape;
+# use Carp::Always;
+
use CrossSell;
use FixMyStreet::Geocode;
use mySociety::AuthToken;
@@ -29,6 +31,13 @@ use mySociety::PostcodeUtil;
use mySociety::Random;
use mySociety::VotingArea;
use mySociety::Web qw(ent NewURL);
+use Utils;
+
+sub debug (@) {
+ return;
+ my ( $format, @args ) = @_;
+ warn sprintf $format, map { defined $_ ? $_ : 'undef' } @args;
+}
BEGIN {
if (!dbh()->selectrow_array('select secret from secret for update of secret')) {
@@ -47,13 +56,13 @@ sub main {
my $id = mySociety::AuthToken::retrieve('partial', $partial);
if ($id) {
my @row = dbh()->selectrow_array(
- "select easting, northing, name, email, title, (photo is not null) as has_photo, phone, detail
+ "select latitude, longitude, name, email, title, (photo is not null) as has_photo, phone, detail
from problem where id=? and state='partial'", {}, $id);
if (@row) {
$q->param('anonymous', 1);
$q->param('submit_map', 1);
- $q->param('easting', $row[0]);
- $q->param('northing', $row[1]);
+ $q->param('latitude', $row[0]);
+ $q->param('longitude', $row[1]);
$q->param('name', $row[2]);
$q->param('email', $row[3]);
$q->param('title', $row[4]);
@@ -82,9 +91,11 @@ sub main {
} elsif ($q->param('id')) {
($out, %params) = display_problem($q, [], {});
$params{title} .= ' - ' . _('Viewing a problem');
- } elsif ($q->param('pc') || ($q->param('x') && $q->param('y')) || ($q->param('e') && $q->param('n'))) {
+ } elsif ($q->param('pc') || ($q->param('x') && $q->param('y')) || ($q->param('lat') || $q->param('lon'))) {
($out, %params) = display_location($q);
$params{title} = _('Viewing a location');
+ } elsif ($q->param('e') && $q->param('n')) {
+ ($out, %params) = redirect_from_osgb_to_wgs84($q);
} else {
($out, %params) = front_page($q);
}
@@ -253,7 +264,7 @@ sub submit_update {
sub submit_problem {
my $q = shift;
- my @vars = qw(council title detail name email phone pc easting northing skipped anonymous category partial upload_fileid lat lon);
+ my @vars = qw(council title detail name email phone pc skipped anonymous category partial upload_fileid latitude longitude);
my %input = map { $_ => scalar $q->param($_) } @vars;
for (qw(title detail)) {
$input{$_} = lc $input{$_} if $input{$_} !~ /[a-z]/;
@@ -265,15 +276,17 @@ sub submit_problem {
my @errors;
my %field_errors;
- if ($input{lat}) {
+
+ # If in UK and we have a lat,lon coocdinate check it is in UK
+ if ( $input{latitude} && mySociety::Config::get('COUNTRY') eq 'GB' ) {
try {
- ($input{easting}, $input{northing}) = mySociety::GeoUtil::wgs84_to_national_grid($input{lat}, $input{lon}, 'G');
+ mySociety::GeoUtil::wgs84_to_national_grid($input{latitude}, $input{longitude}, 'G');
} catch Error::Simple with {
my $e = shift;
push @errors, "We had a problem with the supplied co-ordinates - outside the UK?";
};
}
-
+
my $fh = $q->upload('photo');
if ($fh) {
my $err = Page::check_photo($q, $fh);
@@ -305,8 +318,9 @@ sub submit_problem {
return display_form($q, \@errors, \%field_errors) if (@errors || scalar keys %field_errors); # Short circuit
my $areas;
- if ($input{easting} && $input{northing}) {
- $areas = mySociety::MaPit::call('point', "27700/$input{easting},$input{northing}");
+ if (defined $input{latitude} && defined $input{longitude}) {
+ my $mapit_query = "4326/$input{longitude},$input{latitude}";
+ $areas = mySociety::MaPit::call( 'point', $mapit_query );
if ($input{council} =~ /^[\d,]+(\|[\d,]+)?$/) {
my $no_details = $1 || '';
my %va = map { $_ => 1 } @$mySociety::VotingArea::council_parent_types;
@@ -345,10 +359,10 @@ sub submit_problem {
$input{council} = join(',', @valid_councils) . $no_details;
}
$areas = ',' . join(',', sort keys %$areas) . ',';
- } elsif ($input{easting} || $input{northing}) {
+ } elsif (defined $input{latitude} || defined $input{longitude}) {
push(@errors, _('Somehow, you only have one co-ordinate. Please try again.'));
} else {
- push(@errors, _('You haven\'t specified any sort of co-ordinates. Please try again.'));
+ push(@errors, _("You haven't specified any sort of co-ordinates. Please try again."));
}
my $image;
@@ -378,10 +392,10 @@ sub submit_problem {
if (my $token = $input{partial}) {
my $id = mySociety::AuthToken::retrieve('partial', $token);
if ($id) {
- dbh()->do("update problem set postcode=?, easting=?, northing=?, title=?, detail=?,
+ dbh()->do("update problem set postcode=?, latitude=?, longitude=?, title=?, detail=?,
name=?, email=?, phone=?, state='confirmed', council=?, used_map='t',
anonymous=?, category=?, areas=?, cobrand=?, cobrand_data=?, confirmed=ms_current_timestamp(),
- lastupdate=ms_current_timestamp() where id=?", {}, $input{pc}, $input{easting}, $input{northing},
+ lastupdate=ms_current_timestamp() where id=?", {}, $input{pc}, $input{latitude}, $input{longitude},
$input{title}, $input{detail}, $input{name}, $input{email},
$input{phone}, $input{council}, $input{anonymous} ? 'f' : 't',
$input{category}, $areas, $cobrand, $cobrand_data, $id);
@@ -400,11 +414,11 @@ Please <a href="/contact">let us know what went on</a> and we\'ll look into it.'
} else {
$id = dbh()->selectrow_array("select nextval('problem_id_seq');");
Utils::workaround_pg_bytea("insert into problem
- (id, postcode, easting, northing, title, detail, name,
+ (id, postcode, latitude, longitude, title, detail, name,
email, phone, photo, state, council, used_map, anonymous, category, areas, lang, cobrand, cobrand_data)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'unconfirmed', ?, ?, ?, ?, ?, ?, ?, ?)", 10,
- $id, $input{pc}, $input{easting}, $input{northing}, $input{title},
+ $id, $input{pc}, $input{latitude}, $input{longitude}, $input{title},
$input{detail}, $input{name}, $input{email}, $input{phone}, $image,
$input{council}, $used_map, $input{anonymous} ? 'f': 't', $input{category},
$areas, $mySociety::Locale::lang, $cobrand, $cobrand_data);
@@ -430,22 +444,29 @@ sub display_form {
push @errors, _('There were problems with your report. Please see below.') if (scalar keys %field_errors);
my ($pin_x, $pin_y, $pin_tile_x, $pin_tile_y) = (0,0,0,0);
- my @vars = qw(title detail name email phone pc easting northing x y skipped council anonymous partial upload_fileid lat lon);
- my %input = map { $_ => $q->param($_) || '' } @vars;
- my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars;
+ my @vars = qw(title detail name email phone pc latitude longitude x y skipped council anonymous partial upload_fileid);
- # Convert lat/lon to easting/northing if given
- if ($input{lat}) {
- try {
- ($input{easting}, $input{northing}) = mySociety::GeoUtil::wgs84_to_national_grid($input{lat}, $input{lon}, 'G');
- $input_h{easting} = $input{easting};
- $input_h{northing} = $input{northing};
- } catch Error::Simple with {
- my $e = shift;
- push @errors, "We had a problem with the supplied co-ordinates - outside the UK?";
- };
+ my %input = ();
+ my %input_h = ();
+
+ foreach my $key (@vars) {
+ my $val = $q->param($key);
+ $input{$key} = defined($val) ? $val : ''; # '0' is valid for longitude
+ $input_h{$key} = ent( $input{$key} );
}
+ # Convert lat/lon to easting/northing if given
+ # if ($input{lat}) {
+ # try {
+ # ($input{easting}, $input{northing}) = mySociety::GeoUtil::wgs84_to_national_grid($input{lat}, $input{lon}, 'G');
+ # $input_h{easting} = $input{easting};
+ # $input_h{northing} = $input{northing};
+ # } catch Error::Simple with {
+ # my $e = shift;
+ # push @errors, "We had a problem with the supplied co-ordinates - outside the UK?";
+ # };
+ # }
+
# Get tile co-ordinates if map clicked
($input{x}) = $input{x} =~ /^(\d+)/; $input{x} ||= 0;
($input{y}) = $input{y} =~ /^(\d+)/; $input{y} ||= 0;
@@ -458,28 +479,30 @@ sub display_form {
# We need either a map click, an E/N, to be skipping the map, or be filling in a partial form
return display_location($q, @errors)
unless ($pin_x && $pin_y)
- || ($input{easting} && $input{northing})
+ || ($input{latitude} && $input{longitude})
|| ($input{skipped} && $input{pc})
|| ($input{partial} && $input{pc});
# Work out some co-ordinates from whatever we've got
- my ($easting, $northing);
+ my ($latitude, $longitude);
if ($input{skipped}) {
# Map is being skipped
- if ($input{easting} && $input{northing}) {
- $easting = $input{easting};
- $northing = $input{northing};
+ if ( length $input{latitude} && length $input{longitude} ) {
+ $latitude = $input{latitude};
+ $longitude = $input{longitude};
} else {
- my ($e, $n, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
- $easting = $e; $northing = $n;
+ my ( $lat, $lon, $error ) =
+ FixMyStreet::Geocode::lookup( $input{pc}, $q );
+ $latitude = $lat;
+ $longitude = $lon;
}
} elsif ($pin_x && $pin_y) {
# tilma map was clicked on
- ($easting, $northing) = FixMyStreet::Map::click_to_os($pin_tile_x, $pin_x, $pin_tile_y, $pin_y);
- } elsif ($input{partial} && $input{pc} && !$input{easting} && !$input{northing}) {
+ ($latitude, $longitude) = FixMyStreet::Map::click_to_wgs84($pin_tile_x, $pin_x, $pin_tile_y, $pin_y);
+ } elsif ( $input{partial} && $input{pc} && !length $input{latitude} && !length $input{longitude} ) {
my $error;
try {
- ($easting, $northing, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
+ ($latitude, $longitude, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
} catch Error::Simple with {
$error = shift;
};
@@ -487,8 +510,8 @@ sub display_form {
return front_page($q, $error) if $error;
} else {
# Normal form submission
- $easting = $input_h{easting};
- $northing = $input_h{northing};
+ $latitude = $input_h{latitude};
+ $longitude = $input_h{longitude};
}
# Look up councils and do checks for the point we've got
@@ -496,7 +519,7 @@ sub display_form {
$parent_types = [qw(DIS LBO MTD UTA LGD COI)] # No CTY
if $q->{site} eq 'emptyhomes';
# XXX: I think we want in_gb_locale around the next line, needs testing
- my $all_councils = mySociety::MaPit::call('point', "27700/$easting,$northing", type => $parent_types);
+ my $all_councils = mySociety::MaPit::call('point', "4326/$longitude,$latitude", type => $parent_types);
# Let cobrand do a check
my ($success, $error_msg) = Cobrand::council_check($cobrand, { all_councils => $all_councils }, $q, 'submit_problem');
@@ -504,10 +527,10 @@ sub display_form {
return front_page($q, $error_msg);
}
- # Ipswich & St Edmundsbury are responsible for everything in their areas, no Suffolk
+ # Ipswich & St Edmundsbury are responsible for everything in their areas, not Suffolk
delete $all_councils->{2241} if $all_councils->{2446} || $all_councils->{2443};
- # Norwich is responsible for everything in its areas, no Norfolk
+ # Norwich is responsible for everything in its areas, not Norfolk
delete $all_councils->{2233} if $all_councils->{2391};
return display_location($q, _('That spot does not appear to be covered by a council.
@@ -587,9 +610,9 @@ EOF
$type = 1;
}
$vars{form_start} = FixMyStreet::Map::display_map($q,
- easting => $easting, northing => $northing,
+ latitude => $latitude, longitude => $longitude,
type => $type,
- pins => [ [ $easting, $northing, 'purple' ] ],
+ pins => [ [ $latitude, $longitude, 'purple' ] ],
);
my $partial_id;
if (my $token = $input{partial}) {
@@ -683,8 +706,8 @@ photo of the problem if you have one), etc.'));
}
$vars{text_help} .= '
-<input type="hidden" name="easting" value="' . $easting . '">
-<input type="hidden" name="northing" value="' . $northing . '">';
+<input type="hidden" name="latitude" value="' . $latitude . '">
+<input type="hidden" name="longitude" value="' . $longitude . '">';
if (@errors) {
$vars{errors} = '<ul class="error"><li>' . join('</li><li>', @errors) . '</li></ul>';
@@ -763,40 +786,87 @@ EOF
return (Page::template_include('report-form', $q, Page::template_root($q), %vars), robots => 'noindex,nofollow');
}
+# redirect from osgb
+sub redirect_from_osgb_to_wgs84 {
+ my ($q) = @_;
+
+ my $e = $q->param('e');
+ my $n = $q->param('n');
+
+ my ( $lat, $lon ) = Utils::convert_en_to_latlon_truncated( $e, $n );
+
+ my $lat_lon_url = NewURL(
+ $q,
+ -retain => 1,
+ e => undef,
+ n => undef,
+ lat => $lat,
+ lon => $lon
+ );
+
+ print $q->redirect(
+ -location => $lat_lon_url,
+ -status => 301, # permanent
+ );
+
+ return '';
+}
+
sub display_location {
my ($q, @errors) = @_;
my $cobrand = Page::get_cobrand($q);
- my @vars = qw(pc x y e n all_pins no_pins);
- my %input = map { $_ => $q->param($_) || '' } @vars;
- my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars;
+ my @vars = qw(pc x y lat lon all_pins no_pins);
- (my $easting) = $input{e} =~ /^(\d+)/; $easting ||= 0;
- (my $northing) = $input{n} =~ /^(\d+)/; $northing ||= 0;
+ my %input = ();
+ my %input_h = ();
+
+ foreach my $key (@vars) {
+ my $val = $q->param($key);
+ $input{$key} = defined($val) ? $val : ''; # '0' is valid for longitude
+ $input_h{$key} = ent( $input{$key} );
+ }
+
+ my $latitude = $input{lat};
+ my $longitude = $input{lon};
# X/Y referring to tiles old-school
(my $x) = $input{x} =~ /^(\d+)/; $x ||= 0;
(my $y) = $input{y} =~ /^(\d+)/; $y ||= 0;
- return front_page($q, @errors) unless $x || $y || $input{pc} || $easting || $northing;
- if ($x && $y) {
+ return front_page( $q, @errors )
+ unless ( $x && $y )
+ || $input{pc}
+ || ( defined $latitude && defined $longitude );
+
+ if ( $x && $y ) {
+
# Convert the tile co-ordinates to real ones.
- $easting = FixMyStreet::Map::tile_to_os($x);
- $northing = FixMyStreet::Map::tile_to_os($y);
- } elsif ($easting && $northing) {
+ ( $latitude, $longitude ) =
+ FixMyStreet::Map::tile_xy_to_wgs84( $x, $y );
+ }
+ elsif ( $latitude && $longitude ) {
+
# Don't need to do anything
- } else {
+ }
+ else {
my $error;
try {
- ($easting, $northing, $error) = FixMyStreet::Geocode::lookup($input{pc}, $q);
- } catch Error::Simple with {
+ ( $latitude, $longitude, $error ) =
+ FixMyStreet::Geocode::lookup( $input{pc}, $q );
+
+ debug 'Looked up postcode "%s": lat: "%s", lon: "%s", error: "%s"',
+ $input{pc}, $latitude, $longitude, $error;
+ }
+ catch Error::Simple with {
$error = shift;
};
- return FixMyStreet::Geocode::list_choices($error, '/', $q) if (ref($error) eq 'ARRAY');
- return front_page($q, $error) if $error;
+ return FixMyStreet::Geocode::list_choices( $error, '/', $q )
+ if ( ref($error) eq 'ARRAY' );
+ return front_page( $q, $error ) if $error;
}
# Check this location is okay to be displayed for the cobrand
- my ($success, $error_msg) = Cobrand::council_check($cobrand, { e => $easting, n => $northing }, $q, 'display_location');
+ my ($success, $error_msg) = Cobrand::council_check($cobrand, { lat => $latitude, lon => $longitude }, $q, 'display_location');
return front_page($q, $error_msg) unless $success;
# Deal with pin hiding/age
@@ -810,10 +880,10 @@ sub display_location {
$interval = '6 months';
}
- my ($on_map_all, $on_map, $around_map, $dist) = FixMyStreet::Map::map_features($q, $easting, $northing, $interval);
+ my ($on_map_all, $on_map, $around_map, $dist) = FixMyStreet::Map::map_features($q, $latitude, $longitude, $interval);
my @pins;
foreach (@$on_map_all) {
- push @pins, [ $_->{easting}, $_->{northing}, $_->{state} eq 'fixed' ? 'green' : 'red' ];
+ push @pins, [ $_->{latitude}, $_->{longitude}, $_->{state} eq 'fixed' ? 'green' : 'red' ];
}
my $on_list = '';
foreach (@$on_map) {
@@ -839,7 +909,7 @@ sub display_location {
$around_list .= $dist . 'km)</small>';
$around_list .= ' <small>' . _('(fixed)') . '</small>' if $_->{state} eq 'fixed';
$around_list .= '</li>';
- push @pins, [ $_->{easting}, $_->{northing}, $_->{state} eq 'fixed' ? 'green' : 'red' ];
+ push @pins, [ $_->{latitude}, $_->{longitude}, $_->{state} eq 'fixed' ? 'green' : 'red' ];
}
$around_list = $q->li(_('No problems found.'))
unless $around_list;
@@ -856,21 +926,27 @@ sub display_location {
my $url_skip = NewURL($q, -retain=>1, pc => undef,
x => undef, 'y' => undef,
- easting => $easting, northing => $northing,
+ latitude => $latitude, longitude => $longitude,
'submit_map'=>1, skipped=>1
);
my $pc_h = ent($q->param('pc') || '');
+
+ # truncate the lat,lon for nicer rss urls
+ my ( $short_lat, $short_lon ) =
+ map { Utils::truncate_coordinate($_) } #
+ ( $latitude, $longitude );
+
my %vars = (
'map' => FixMyStreet::Map::display_map($q,
- easting => $easting, northing => $northing,
+ latitude => $latitude, longitude => $longitude,
type => 1,
pins => \@pins,
post => $map_links
),
map_end => FixMyStreet::Map::display_map_end(1),
url_home => Cobrand::url($cobrand, '/', $q),
- url_rss => Cobrand::url($cobrand, NewURL($q, -retain => 1, -url=> "/rss/n/$easting,$northing", pc => undef, x => undef, 'y' => undef), $q),
- url_email => Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, -url=>'/alert', e=>$easting, 'n'=>$northing, feed=>"local:$easting:$northing"), $q),
+ url_rss => Cobrand::url($cobrand, NewURL($q, -retain => 1, -url=> "/rss/l/$short_lat,$short_lon", pc => undef, x => undef, y => undef, lat => undef, lon => undef ), $q),
+ url_email => Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, lat => $short_lat, lon => $short_lon, -url=>'/alert', feed=>"local:$short_lat:$short_lon"), $q),
url_skip => $url_skip,
email_me => _('Email me new local problems'),
rss_alt => _('RSS feed'),
@@ -890,7 +966,7 @@ sub display_location {
);
my %params = (
- rss => [ _('Recent local problems, FixMyStreet'), "/rss/n/$easting,$northing" ],
+ rss => [ _('Recent local problems, FixMyStreet'), "/rss/l/$short_lat,$short_lon" ],
robots => 'noindex,nofollow',
);
@@ -931,9 +1007,12 @@ sub display_problem {
my $extra_data = Cobrand::extra_data($cobrand, $q);
my $google_link = Cobrand::base_url_for_emails($cobrand, $extra_data)
. '/report/' . $problem->{id};
- my ($lat, $lon) = mySociety::GeoUtil::national_grid_to_wgs84($problem->{easting}, $problem->{northing}, 'G');
- my $map_links = "<p id='sub_map_links'><a href=\"http://maps.google.co.uk/maps?output=embed&amp;z=16&amp;q="
- . URI::Escape::uri_escape_utf8($problem->{title} . ' - ' . $google_link) . "\@$lat,$lon\">View on Google Maps</a></p>";
+
+ my $map_links =
+ "<p id='sub_map_links'>"
+ . "<a href=\"http://maps.google.co.uk/maps?output=embed&amp;z=16&amp;q="
+ . URI::Escape::uri_escape_utf8( $problem->{title} . ' - ' . $google_link )
+ . "\@$problem->{latitude},$problem->{longitude}\">View on Google Maps</a></p>";
my $banner;
if ($q->{site} ne 'emptyhomes' && $problem->{state} eq 'confirmed' && $problem->{duration} > 8*7*24*60*60) {
@@ -945,7 +1024,7 @@ sub display_problem {
my $contact_url = Cobrand::url($cobrand, NewURL($q, -retain => 1, pc => undef, x => undef, 'y' => undef, -url=>'/contact?id=' . $input{id}), $q);
my $back = Cobrand::url($cobrand, NewURL($q, -url => '/',
- 'e' => int($problem->{easting}), 'n' => int($problem->{northing}),
+ lat => $problem->{latitude}, lon => $problem->{longitude},
-retain => 1, pc => undef, x => undef, 'y' => undef, id => undef
), $q);
my $fixed = ($input{fixed}) ? ' checked' : '';
@@ -953,9 +1032,9 @@ sub display_problem {
my %vars = (
banner => $banner,
map_start => FixMyStreet::Map::display_map($q,
- easting => $problem->{easting}, northing => $problem->{northing},
+ latitude => $problem->{latitude}, longitude => $problem->{longitude},
type => 0,
- pins => [ [ $problem->{easting}, $problem->{northing}, 'blue' ] ],
+ pins => [ [ $problem->{latitude}, $problem->{longitude}, 'blue' ] ],
post => $map_links
),
map_end => FixMyStreet::Map::display_map_end(0),