aboutsummaryrefslogtreecommitdiffstats
path: root/web/import.cgi
blob: 371e70f7aa3cb77f128f138c4ad07de50c140be6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/perl -w -I../perllib

# import.cgi
# Script to which things like iPhones can POST new data
#
# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved.
# Email: matthew@mysociety.org. WWW: http://www.mysociety.org
#
# $Id: import.cgi,v 1.11 2009-12-10 16:22:49 matthew Exp $

use strict;
use Error qw(:try);
use Standard;
use Utils;
use mySociety::AuthToken;
use mySociety::Config;
use mySociety::EmailUtil;

sub main {
    my $q = shift;

    my @vars = qw(service subject detail name email phone easting northing lat lon id phone_id);
    my %input = map { $_ => $q->param($_) || '' } @vars;
    my @errors;

    unless ($ENV{REQUEST_METHOD} eq 'POST') {
        print Page::header($q, title=>'External import');
        docs();
        print Page::footer($q);
        return;
    }

    # If we were given easting, northing convert to lat lon now
    my $latitude  = $input{lat} ||= 0;
    my $longitude = $input{lon} ||= 0;
    if (
        !( $latitude || $longitude )    # have not been given lat or lon
        && ( $input{easting} && $input{northing} )    # but do have e and n
      )
    {
        ( $latitude, $longitude ) =
          Utils::convert_en_to_latlon( $input{easting}, $input{northing});
    }

    my $fh = $q->upload('photo'); # MUST come before $q->header, don't know why!
    print $q->header(-charset => 'utf-8', -content_type => 'text/plain');

    if ($fh) {
        my $err = Page::check_photo($q, $fh);
        push @errors, $err if $err;
    }

    push @errors, 'You must supply a service' unless $input{service};
    push @errors, 'Please enter a subject' unless $input{subject} && $input{subject} =~ /\S/;
    push @errors, 'Please enter your name' unless $input{name} && $input{name} =~ /\S/;

    if (!$input{email} || $input{email} !~ /\S/) {
        push @errors, 'Please enter your email';
    } elsif (!mySociety::EmailUtil::is_valid_email($input{email})) {
        push @errors, 'Please enter a valid email';
    }

    if ( $latitude && mySociety::Config::get('COUNTRY') eq 'GB' ) {
        try {
            Utils::convert_latlon_to_en( $latitude, $longitude );
        } catch Error::Simple with {
            my $e = shift;
            push @errors, "We had a problem with the supplied co-ordinates - outside the UK?";
        };
    }

    # TODO: Get location from photo if present in EXIF data?

    my $photo;
    if ($fh) {
        try {
            $photo = Page::process_photo($fh, 1);
        } catch Error::Simple with {
            my $e = shift;
            push @errors, "That photo doesn't appear to have uploaded correctly ($e), please try again.";
        };
    }

    unless ( $photo || ( $latitude || $longitude ) ) {
        push @errors, 'Either a location or a photo must be provided.';
    }

    if (@errors) {
        print map { "ERROR:$_\n" } @errors;
        return;
    }

    # Store for possible future use
    if ($input{id} || $input{phone_id}) {
        my $id = $input{id} || $input{phone_id};
        my $already = dbh()->selectrow_array('select id from partial_user where service=? and nsid=?', {}, $input{service}, $id);
        unless ($already) {
            dbh()->do('insert into partial_user (service, nsid, name, email, phone) values (?, ?, ?, ?, ?)',
                {}, $input{service}, $id, $input{name}, $input{email}, $input{phone});
        }
    }

    # Store what we have so far in the database
    my $id = dbh()->selectrow_array("select nextval('problem_id_seq')");
    Utils::workaround_pg_bytea("insert into problem
        (id, postcode, latitude, longitude, title, detail, name, service,
         email, phone, photo, state, used_map, anonymous, category, areas)
        values
        (?, '', ?, ?, ?, ?, ?, ?, ?, ?, ?, 'partial', 't', 'f', '', '')", 10,
        $id, $latitude, $longitude, $input{subject},
        $input{detail}, $input{name}, $input{service}, $input{email}, $input{phone}, $photo);

    my $token = mySociety::AuthToken::store('partial', $id);
    my %h = (
        name => $input{name} ? ' ' . $input{name} : '',
        url => Page::base_url_with_lang($q, undef, 1) . '/L/' . $token,
        service => $input{service},
        title => $input{title},
        detail => $input{detail},
    );

    Page::send_email($q, $input{email}, $input{name}, 'partial', %h);

    dbh()->commit();
    print 'SUCCESS';
}

Page::do_fastcgi(\&main);

sub docs {
    print <<EOF;
<p>You may inject problem reports into FixMyStreet programatically using this
simple interface. Upon receipt, an email will be sent to the address given,
with a link the user must click in order to check the details of their report,
add any other information they wish, and then submit to the council.

<p>This interface returns a plain text response; either <samp>SUCCESS</samp> if
the report has been successfully received, or if not, a list of errors, one per
line each starting with <samp>ERROR:</samp>.

<p>You may submit the following information by POST to this URL
(i.e. <samp>http://www.fixmystreet.com/import</samp> ):</p>
<dl>
<dt>service
<dd>
<em>Required</em>.
Name of application/service using this interface.
<dt>id
<dd>Unique ID of a user/device, for possible future use.
<br><small>(e.g. used by Flickr import to know which accounts to look at)</small>
<dt>subject
<dd>
<em>Required</em>. Subject of problem report.
<dt>detail
<dd>Main body and details of problem report.
<dt>name
<dd>
<em>Required</em>. Name of problem reporter.
<dt>email
<dd>
<em>Required</em>. Email address of problem reporter.
<dt>phone
<dd>Telephone number of problem reporter.
<dt>easting / northing
<dt>lat / lon
<dd>Location of problem report. You can either supply eastings/northings, or WGS84 latitude/longitude.
<dt>photo
<dd>Photo of problem (JPEG only).
</dl>
EOF
}