#!/usr/bin/perl -w -I../perllib
# index.cgi:
# Main code for FixMyStreet
#
# Copyright (c) 2006 UK Citizens Online Democracy. All rights reserved.
# Email: matthew@mysociety.org. WWW: http://www.mysociety.org
#
# $Id: index.cgi,v 1.183 2008-03-28 15:11:48 matthew Exp $
use strict;
use Standard;
use Error qw(:try);
use File::Slurp;
use Image::Magick;
use LWP::Simple;
use RABX;
use CGI::Carp;
use URI::Escape;
use mySociety::AuthToken;
use mySociety::Config;
use mySociety::DBHandle qw(select_all);
use mySociety::EmailUtil;
use mySociety::Gaze;
use mySociety::GeoUtil;
use mySociety::MaPit;
use mySociety::PostcodeUtil;
use mySociety::Random;
use mySociety::VotingArea;
use mySociety::Web qw(ent NewURL);
BEGIN {
if (!dbh()->selectrow_array('select secret from secret for update of secret')) {
local dbh()->{HandleError};
dbh()->do('insert into secret (secret) values (?)', {}, unpack('h*', mySociety::Random::random_bytes(32)));
}
dbh()->commit();
}
# Main code for index.cgi
sub main {
my $q = shift;
my $out = '';
my %params;
if ($q->param('submit_problem') || ($q->param('submit_map') && $q->param('submit_map')==2)) {
$params{title} = 'Submitting your problem';
($out) = submit_problem($q);
} elsif ($q->param('submit_update')) {
$params{title} = 'Submitting your update';
($out) = submit_update($q);
} elsif ($q->param('submit_map')) {
$params{title} = 'Reporting a problem';
($out) = display_form($q);
} elsif ($q->param('id')) {
($out, %params) = display_problem($q);
$params{title} .= ' - Viewing a problem';
} elsif ($q->param('pc') || ($q->param('x') && $q->param('y'))) {
($out, %params) = display_location($q);
$params{title} = 'Viewing a location';
} else {
$out = front_page($q);
}
print Page::header($q, %params);
print $out;
print Page::footer($q);
}
Page::do_fastcgi(\&main);
# Display front page
sub front_page {
my ($q, $error) = @_;
my $pc_h = ent($q->param('pc') || '');
my $out = <
(like graffiti, fly tipping, broken paving slabs, or street lighting)
' . $error . '
' if ($error); my $fixed = dbh()->selectrow_array("select count(*) from problem where state='fixed' and lastupdate>ms_current_timestamp()-'1 month'::interval"); my $updates = dbh()->selectrow_array("select count(*) from comment where state='confirmed'"); my $new = dbh()->selectrow_array("select count(*) from problem where state in ('confirmed','fixed') and confirmed>ms_current_timestamp()-'1 week'::interval"); my $new_text = 'in past week'; if ($new > $fixed) { $new = dbh()->selectrow_array("select count(*) from problem where state in ('confirmed','fixed') and confirmed>ms_current_timestamp()-'3 days'::interval"); $new_text = 'recently'; } $out .= 'You have located the problem at the point marked with a purple pin on the map. If this is not the correct location, simply click on the map again. '; } if ($details eq 'all') { $out .= '
All the information you provide here will be sent to ' . join(' or ', map { $areas_info->{$_}->{name} } @$all_councils) . '. On the site, we will show the subject and details of the problem, plus your name if you give us permission.'; $out .= ''; } elsif ($details eq 'some') { my $e = mySociety::Config::get('CONTACT_EMAIL'); my %councils = map { $_ => 1 } @councils; my @missing; foreach (@$all_councils) { push @missing, $_ unless $councils{$_}; } my $n = @missing; my $list = join(' or ', map { $areas_info->{$_}->{name} } @missing); $out .= '
All the information you provide here will be sent to ' . join(' or ', map { $areas_info->{$_}->{name} } @councils) . '. On the site, we will show the subject and details of the problem, plus your name if you give us permission.'; $out .= ' We do not yet have details for the other council'; $out .= ($n>1) ? 's that cover' : ' that covers'; $out .= " this location. You can help us by finding a contact email address for local problems for $list and emailing it to us at $e."; $out .= ''; } else { my $e = mySociety::Config::get('CONTACT_EMAIL'); my $list = join(' or ', map { $areas_info->{$_}->{name} } @$all_councils); my $n = @$all_councils; $out .= '
We do not yet have details for the council'; $out .= ($n>1) ? 's that cover' : ' that covers'; $out .= " this location. If you submit a problem here it will be left on the site, but not reported to the council. You can help us by finding a contact email address for local problems for $list and emailing it to us at $e."; $out .= ''; } if ($input{skipped}) { $out .= '
Please fill in the form below with details of the problem, and describe the location as precisely as possible in the details box.'; } elsif ($details ne 'none') { $out .= '
Please fill in details of the problem below. The council won\'t be able to help unless you leave as much detail as you can, so please describe the exact location of the problem (e.g. on a wall), what it is, how long it has been there, a description (and a photo of the problem if you have one), etc.'; } else { $out .= '
Please fill in details of the problem below.'; } $out .= ' '; if (@errors) { $out .= '
The photo you uploaded was:
'; $out .= 'Please note:
If you cannot see a map – if you have images turned off, or are using a text only browser, for example – and you wish to report a problem, please skip this step and we will ask you to describe the location of your problem instead.
EOF $out .= <No problems have been reported yet.
'; } $out .= <No problems have been reported yet.
'; } $out .= <No problems have been fixed yet
'; } $out .= ''; $out .= Page::display_map_end(1); my %params = ( rss => [ 'Recent local problems, FixMyStreet', "/rss/$x,$y" ] ); return ($out, %params); } sub display_problem { my ($q, @errors) = @_; my @vars = qw(id name email update fixed x y); my %input = map { $_ => $q->param($_) || '' } @vars; my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars; $input{x} ||= 0; $input{x} += 0; $input{y} ||= 0; $input{y} += 0; # Get all information from database return display_location($q, 'Unknown problem ID') if $input{id} =~ /\D/; my $problem = dbh()->selectrow_hashref( "select id, easting, northing, council, category, title, detail, photo, used_map, name, anonymous, extract(epoch from confirmed) as time, state, extract(epoch from whensent-confirmed) as whensent, extract(epoch from ms_current_timestamp()-lastupdate) as duration from problem where id=? and state in ('confirmed','fixed', 'hidden')", {}, $input{id}); return display_location($q, 'Unknown problem ID') unless $problem; return front_page($q, 'That problem has been hidden from public view as it contained inappropriate public details') if $problem->{state} eq 'hidden'; my $x = Page::os_to_tile($problem->{easting}); my $y = Page::os_to_tile($problem->{northing}); my $x_tile = $input{x} || int($x); my $y_tile = $input{y} || int($y); my $px = Page::os_to_px($problem->{easting}, $x_tile); my $py = Page::os_to_px($problem->{northing}, $y_tile); my $out = ''; my $pins = Page::display_pin($q, $px, $py, 'blue'); $out .= Page::display_map($q, x => $x_tile, y => $y_tile, type => 0, pins => $pins, px => $px, py => $py ); if ($problem->{state} eq 'confirmed' && $problem->{duration} > 8*7*24*60*60) { $out .= $q->p({id => 'unknown'}, _('This problem is old and of unknown status.')) } if ($problem->{state} eq 'fixed') { $out .= $q->p({id => 'fixed'}, _('This problem has been fixed.')) } $out .= Page::display_problem_text($q, $problem); $out .= $q->p({align=>'right'}, $q->small($q->a({href => '/contact?id=' . $input{id}}, 'Offensive? Unsuitable? Tell us')) ); # Try and have pin near centre of map $x_tile -= 1 if $x - $x_tile < 0.5; $y_tile -= 1 if $y - $y_tile < 0.5; my $back = NewURL($q, id=>undef, x=>$x_tile, y=>$y_tile, submit_update=>undef); $out .= ''; $out .= 'Receive email when updates are left on this problem
EOF $out .= '