aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/general-example3
-rw-r--r--perllib/Page.pm5
-rw-r--r--web/css/core.css51
-rwxr-xr-xweb/index.cgi58
-rw-r--r--web/js.js89
-rwxr-xr-xweb/upload.cgi56
6 files changed, 250 insertions, 12 deletions
diff --git a/conf/general-example b/conf/general-example
index 7b3c79c72..701401540 100644
--- a/conf/general-example
+++ b/conf/general-example
@@ -14,7 +14,7 @@
* Copyright (c) 2006 UK Citizens Online Democracy. All rights reserved.
* Email: francis@mysociety.org; WWW: http://www.mysociety.org
*
- * $Id: general-example,v 1.15 2008-01-28 15:27:00 matthew Exp $
+ * $Id: general-example,v 1.16 2008-03-29 03:03:34 matthew Exp $
*
*/
@@ -36,6 +36,7 @@ define('OPTION_CONTACT_EMAIL', 'team@example.org');
define('OPTION_CONTACT_NAME', 'FixMyStreet');
define('OPTION_STAGING_SITE', 1);
+define('OPTION_UPLOAD_CACHE', '/upload/');
define('OPTION_GEO_CACHE', '/cache/');
define('OPTION_GOOGLE_MAPS_API_KEY', '');
diff --git a/perllib/Page.pm b/perllib/Page.pm
index 916918686..8d0ac69d4 100644
--- a/perllib/Page.pm
+++ b/perllib/Page.pm
@@ -6,7 +6,7 @@
# Copyright (c) 2006 UK Citizens Online Democracy. All rights reserved.
# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
#
-# $Id: Page.pm,v 1.83 2008-03-28 16:36:47 matthew Exp $
+# $Id: Page.pm,v 1.84 2008-03-29 03:03:35 matthew Exp $
#
package Page;
@@ -108,6 +108,9 @@ sub header ($%) {
<html lang="en-gb">
<head>
<script type="text/javascript" src="/yui/utilities.js"></script>
+ <script type="text/javascript" src="/jslib/swfupload/swfupload.js"></script>
+ <script type="text/javascript" src="/jslib/swfupload/FileProgress.js"></script>
+ <script type="text/javascript" src="/jslib/swfupload/swfupload.graceful_degradation.js"></script>
<script type="text/javascript" src="/js.js"></script>
<title>${title}FixMyStreet</title>
<style type="text/css">\@import url("/css/core.css"); \@import url("/css/main.css");</style>
diff --git a/web/css/core.css b/web/css/core.css
index 9a40bd052..c2e32909a 100644
--- a/web/css/core.css
+++ b/web/css/core.css
@@ -357,3 +357,54 @@ p#copyright {
#content { max-width: none; }
#side { margin-right: 0; }
}
+
+/* File upload */
+.progressContainer {
+ margin: 5px;
+ padding: 4px;
+ width: 357px;
+ border: solid 1px #E8E8E8;
+ background-color: #F7F7F7;
+ overflow: hidden;
+}
+.red { border: solid 1px #B50000; background-color: #FFEBEB; }
+.green { border: solid 1px #DDF0DD; background-color: #EBFFEB; }
+.blue { border: solid 1px #CEE2F2; background-color: #F0F5FF; }
+
+.progressName {
+ font-size: 8pt;
+ font-weight: bold;
+ color: #555555;
+ width: 323px;
+ height: 14px;
+ text-align: left;
+ white-space: nowrap;
+ overflow: hidden;
+}
+.progressBarInProgress, .progressBarComplete, .progressBarError {
+ font-size: 0px;
+ width: 0%;
+ height: 2px;
+ background-color: blue;
+ margin-top: 2px;
+}
+.progressBarComplete {
+ width: 100%;
+ background-color: green;
+ visibility: hidden;
+}
+.progressBarError {
+ width: 100%;
+ background-color: red;
+ visibility: hidden;
+}
+.progressBarStatus {
+ margin-top: 2px;
+ width: 337px;
+ font-size: 7pt;
+ font-family: Verdana;
+ text-align: left;
+ white-space: nowrap;
+}
+
+
diff --git a/web/index.cgi b/web/index.cgi
index ee2586f39..3f5794a86 100755
--- a/web/index.cgi
+++ b/web/index.cgi
@@ -6,7 +6,7 @@
# Copyright (c) 2006 UK Citizens Online Democracy. All rights reserved.
# Email: matthew@mysociety.org. WWW: http://www.mysociety.org
#
-# $Id: index.cgi,v 1.184 2008-03-28 16:36:48 matthew Exp $
+# $Id: index.cgi,v 1.185 2008-03-29 03:03:35 matthew Exp $
use strict;
use Standard;
@@ -155,7 +155,7 @@ EOF
sub submit_update {
my $q = shift;
- my @vars = qw(id name email update fixed);
+ my @vars = qw(id name email update fixed upload_fileid);
my %input = map { $_ => $q->param($_) || '' } @vars;
my @errors;
@@ -183,6 +183,12 @@ sub submit_update {
};
}
+ if ($input{upload_fileid}) {
+ open FP, mySociety::Config::get('UPLOAD_CACHE') . $input{upload_fileid};
+ $image = join('', <FP>);
+ close FP;
+ }
+
return display_problem($q, @errors) if (@errors);
my $id = dbh()->selectrow_array("select nextval('comment_id_seq');");
@@ -217,7 +223,7 @@ sub workaround_pg_bytea {
sub submit_problem {
my $q = shift;
- my @vars = qw(council title detail name email phone pc easting northing skipped anonymous category flickr);
+ my @vars = qw(council title detail name email phone pc easting northing skipped anonymous category flickr upload_fileid);
my %input = map { $_ => scalar $q->param($_) } @vars;
for (qw(title detail)) {
$input{$_} = lc $input{$_} if $input{$_} !~ /[a-z]/;
@@ -311,6 +317,12 @@ sub submit_problem {
};
}
+ if ($input{upload_fileid}) {
+ open FP, mySociety::Config::get('UPLOAD_CACHE') . $input{upload_fileid};
+ $image = join('', <FP>);
+ close FP;
+ }
+
return display_form($q, @errors) if (@errors);
delete $input{council} if $input{council} eq '-1';
@@ -359,7 +371,7 @@ sub submit_problem {
sub display_form {
my ($q, @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 flickr);
+ my @vars = qw(title detail name email phone pc easting northing x y skipped council anonymous flickr upload_fileid);
my %input = map { $_ => $q->param($_) || '' } @vars;
my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars;
my @ps = $q->param;
@@ -546,8 +558,16 @@ EOF
}
} else {
$out .= <<EOF;
-<div><label for="form_photo">Photo:</label>
-<input type="file" name="photo" id="form_photo"></div>
+<div id="fileupload_flashUI" style="display:none">
+<label for="form_photo">Photo:</label>
+<input type="text" id="txtfilename" disabled="true" style="background-color: #ffffff;">
+<input type="button" value="Browse..." onclick="document.getElementById('txtfilename').value=''; swfu.cancelUpload(); swfu.selectFile();">
+<input type="hidden" name="upload_fileid" id="upload_fileid" value="$input_h{upload_fileid}">
+</div>
+<div id="fileupload_normalUI">
+<label for="form_photo">Photo:</label>
+<input type="file" name="photo" id="form_photo">
+</div>
EOF
}
$out .= <<EOF;
@@ -576,6 +596,11 @@ directly using their own website.
</div>
EOF
$out .= Page::display_map_end(1);
+ $out .= <<EOF;
+<script type="text/javascript">
+swfu = new SWFUpload(swfu_settings);
+</script>
+EOF
return $out;
}
@@ -678,7 +703,7 @@ EOF
sub display_problem {
my ($q, @errors) = @_;
- my @vars = qw(id name email update fixed x y);
+ my @vars = qw(id name email update fixed upload_fileid x y);
my %input = map { $_ => $q->param($_) || '' } @vars;
my %input_h = map { $_ => $q->param($_) ? ent($q->param($_)) : '' } @vars;
$input{x} ||= 0; $input{x} += 0;
@@ -761,12 +786,25 @@ EOF
<div><label for="form_update">Update:</label>
<textarea name="update" id="form_update" rows="7" cols="30">$input_h{update}</textarea></div>
$fixedline
-<div><label for="form_photo">Photo:</label>
-<input type="file" name="photo" id="form_photo"></div>
-<div class="checkbox"><input type="submit" value="Post"></div>
+<div id="fileupload_flashUI" style="display:none">
+<label for="form_photo">Photo:</label>
+<input type="text" id="txtfilename" disabled="true" style="background-color: #ffffff;">
+<input type="button" value="Browse..." onclick="document.getElementById('txtfilename').value=''; swfu.cancelUpload(); swfu.selectFile();">
+<input type="hidden" name="upload_fileid" id="upload_fileid" value="$input_h{upload_fileid}">
+</div>
+<div id="fileupload_normalUI">
+<label for="form_photo">Photo:</label>
+<input type="file" name="photo" id="form_photo">
+</div>
+<div class="checkbox"><input type="submit" id="update_post" value="Post"></div>
</form>
EOF
$out .= Page::display_map_end(0);
+ $out .= <<EOF;
+<script type="text/javascript">
+swfu = new SWFUpload(swfu_settings);
+</script>
+EOF
my %params = (
rss => [ 'Updates to this problem, FixMyStreet', "/rss/$input_h{id}" ],
diff --git a/web/js.js b/web/js.js
index 58ca485a0..2634f481a 100644
--- a/web/js.js
+++ b/web/js.js
@@ -56,6 +56,10 @@ YAHOO.util.Event.onContentReady('mapForm', function() {
}
this.x.value = x + 2;
this.y.value = y + 2;
+ if (swfu && swfu.getStats().files_queued > 0) {
+ swfu.startUpload();
+ return false;
+ }
return true;
}
});
@@ -110,6 +114,91 @@ YAHOO.util.Event.onContentReady('email_alert_box', function() {
});
});
+/* File upload */
+function doSubmit(e) {
+ e = e || window.event;
+ if (e.stopPropagation) e.stopPropagation();
+ e.cancelBubble = true;
+ try {
+ if (swfu.getStats().files_queued > 0)
+ swfu.startUpload();
+ else
+ return true;
+ } catch (e) {}
+ return false;
+}
+
+function uploadDone() {
+ var m = document.getElementById('mapForm');
+ if (m) {
+ m.submit();
+ } else {
+ document.getElementById('fieldset').submit();
+ }
+}
+
+var swfu;
+var swfu_settings = {
+ upload_url : "http://matthew.bci.mysociety.org/upload.cgi",
+ flash_url : "http://matthew.bci.mysociety.org/jslib/swfupload/swfupload_f9.swf",
+ file_size_limit : "10240",
+ file_types : "*.jpg;*.jpeg;*.pjpeg",
+ file_types_description : "JPEG files",
+ file_upload_limit : "0",
+
+ swfupload_loaded_handler : function() {
+ var d = document.getElementById("fieldset");
+ if (d) d.onsubmit = doSubmit;
+ },
+ file_queued_handler : function(obj) {
+ document.getElementById('txtfilename').value = obj.name;
+ },
+//file_queue_error_handler : fileQueueError,
+ // file_dialog_complete_handler : fileDialogComplete,
+//upload_start_handler : uploadStartEventHandler,
+ upload_progress_handler : function(obj, bytesLoaded, bytesTotal) {
+ var percent = Math.ceil((bytesLoaded / bytesTotal) * 100);
+ obj.id = "singlefile";
+ var progress = new FileProgress(obj, this.customSettings.progress_target);
+ progress.setProgress(percent);
+ progress.setStatus("Uploading...");
+ },
+ upload_success_handler : function(obj, server_data) {
+ obj.id = "singlefile";
+ var progress = new FileProgress(obj, this.customSettings.progress_target);
+ progress.setComplete();
+ progress.setStatus("Complete!");
+ if (server_data == ' ') {
+ this.customSettings.upload_successful = false;
+ } else {
+ this.customSettings.upload_successful = true;
+ document.getElementById('upload_fileid').value = server_data;
+ }
+ },
+ upload_complete_handler : function(obj) {
+ if (this.customSettings.upload_successful) {
+ var d = document.getElementById('update_post');
+ if (d) d.disabled = 'true';
+ uploadDone();
+ } else {
+ obj.id = 'singlefile';
+ var progress = new FileProgress(obj, this.customSettings.progress_target);
+ progress.setError();
+ progress.setStatus("File rejected");
+ document.getElementById('txtfilename').value = '';
+ }
+
+ },
+//upload_error_handler : uploadError,
+
+ swfupload_element_id : "fileupload_flashUI",
+ degraded_element_id : "fileupload_normalUI",
+ custom_settings : {
+ upload_successful : false,
+ progress_target : 'fileupload_flashUI'
+ }
+};
+
// I love the global
var tile_x = 0;
var tile_y = 0;
diff --git a/web/upload.cgi b/web/upload.cgi
new file mode 100755
index 000000000..bc42716f8
--- /dev/null
+++ b/web/upload.cgi
@@ -0,0 +1,56 @@
+#!/usr/bin/perl -w -I../perllib -I../../perllib
+
+# upload.cgi:
+# Receiver of flash upload files
+#
+# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved.
+# Email: matthew@mysociety.org. WWW: http://www.mysociety.org
+#
+# $Id: upload.cgi,v 1.1 2008-03-29 03:03:35 matthew Exp $
+
+use strict;
+use Standard -db;
+
+use Error qw(:try);
+use Image::Magick;
+use mySociety::Random qw(random_bytes);
+
+# Main code for index.cgi
+sub main {
+ my $q = shift;
+
+ print $q->header(-type => 'text/plain');
+ my $out = ' ';
+ try {
+ my $fh = $q->upload('Filedata');
+ my $image;
+ if ($fh) {
+ $q->delete('photo'); # Can't check content/type when uploaded with Flash
+ $image = process_photo($fh);
+ my $name = unpack('H*', random_bytes(12));
+ open FP, '>/data/vhost/matthew.bci.mysociety.org/photos/' . $name or throw Error::Simple('could not open file');
+ print FP $image;
+ close FP;
+ $out = $name;
+ };
+ } catch Error::Simple with {
+ my $e = shift;
+ };
+ print $out;
+}
+Page::do_fastcgi(\&main);
+
+sub process_photo {
+ my $fh = shift;
+ my $photo = Image::Magick->new;
+ my $err = $photo->Read(file => \*$fh); # Mustn't be stringified
+ close $fh;
+ throw Error::Simple("read failed: $err") if "$err";
+ $err = $photo->Scale(geometry => "250x250>");
+ throw Error::Simple("resize failed: $err") if "$err";
+ my @blobs = $photo->ImageToBlob();
+ undef $photo;
+ $photo = $blobs[0];
+ return $photo;
+}
+