diff options
author | Marius Halden <marius.h@lden.org> | 2016-07-06 19:53:50 +0200 |
---|---|---|
committer | Marius Halden <marius.h@lden.org> | 2016-07-06 19:53:50 +0200 |
commit | 02edc2af388e8e77c6da876bcec3633ea9161083 (patch) | |
tree | 59e65ccfc88c0795476db7ae709013862c7161c3 | |
parent | 2cf7f0dcf146143613beb102d0dd227238776b69 (diff) | |
parent | 26ef9e161e7ca4bbcf6bcbddb1ba4f215bc349ec (diff) |
Oppgrader til 1.8.4fiksgatami-prod-1.8
Merge branch 'fiksgatami-dev' into fiksgatami-prod
67 files changed, 499 insertions, 328 deletions
@@ -45,6 +45,22 @@ web-based cross-browser testing tools for this project. ## Releases +* v1.8.4 (6th July 2016) + - Security: + - Fix XSS vulnerability in OpenGraph header and hide/all pins links. + - Front end improvements: + - Wrap emails better for differing screen sizes. #1393 + - Fix annoying jump when "Get updates" drawer opened. #1425 + - Improve auth flow taken when return key used. #1433 + - Add and improve more CSRF tokens. #1433 + - Remove default box-shadow. #1419 + - Fix missing margin before reporting form email input. #1418 + - Bugfixes: + - Redirect correctly if filter used without JavaScript. #1422 + - Remove race condition when starting new report. #1434 + - Fix a couple of display bugs in IE7. #1356 + - Correctly orient preview images. #1378 + * v1.8.3 (3rd June 2016) - Admin improvements - Add search boxes to admin index page, and move stats. #1295 diff --git a/bin/site-specific-install.sh b/bin/site-specific-install.sh index 71bfc11ff..039434d03 100644 --- a/bin/site-specific-install.sh +++ b/bin/site-specific-install.sh @@ -1,7 +1,7 @@ #!/bin/sh # Set this to the version we want to check out -VERSION=${VERSION_OVERRIDE:-v1.8.3} +VERSION=${VERSION_OVERRIDE:-v1.8.4} PARENT_SCRIPT_URL=https://github.com/mysociety/commonlib/blob/master/bin/install-site.sh diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index 4e288556f..72c6baad3 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -215,7 +215,7 @@ sub bodies : Path('bodies') : Args(0) { return; } - $c->forward( 'get_token' ); + $c->forward( '/auth/get_csrf_token' ); my $edit_activity = $c->model('DB::ContactsHistory')->search( undef, @@ -232,7 +232,7 @@ sub bodies : Path('bodies') : Args(0) { my $posted = $c->get_param('posted') || ''; if ( $posted eq 'body' ) { $c->forward('check_for_super_user'); - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my $params = $c->forward('body_params'); my $body = $c->model('DB::Body')->create( $params ); @@ -289,7 +289,7 @@ sub body : Path('body') : Args(1) { $c->stash->{body_id} = $body_id; $c->forward( 'check_for_super_user' ); - $c->forward( 'get_token' ); + $c->forward( '/auth/get_csrf_token' ); $c->forward( 'lookup_body' ); $c->forward( 'fetch_all_bodies' ); $c->forward( 'body_form_dropdowns' ); @@ -318,7 +318,7 @@ sub update_contacts : Private { my $editor = $c->forward('get_user'); if ( $posted eq 'new' ) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my %errors; @@ -370,7 +370,7 @@ sub update_contacts : Private { } } elsif ( $posted eq 'update' ) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my @categories = $c->get_param_list('confirmed'); @@ -393,7 +393,7 @@ sub update_contacts : Private { $c->stash->{updated} = _('Values updated'); } elsif ( $posted eq 'body' ) { $c->forward('check_for_super_user'); - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my $params = $c->forward( 'body_params' ); $c->stash->{body}->update( $params ); @@ -476,7 +476,7 @@ sub category_edit : Path('body') : Args(2) { $c->stash->{body_id} = $body_id; - $c->forward( 'get_token' ); + $c->forward( '/auth/get_csrf_token' ); $c->forward( 'lookup_body' ); my $contact = $c->stash->{body}->contacts->search( { category => $category } )->first; @@ -643,7 +643,7 @@ sub report_edit : Path('report_edit') : Args(1) { $c->stash->{problem} = $problem; - $c->forward('get_token'); + $c->forward('/auth/get_csrf_token'); if ( $c->cobrand->moniker eq 'zurich' ) { $c->stash->{page} = 'admin'; @@ -689,7 +689,7 @@ sub report_edit : Path('report_edit') : Args(1) { ->all ]; if ( $c->get_param('resend') ) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); $problem->whensent(undef); $problem->update(); @@ -699,7 +699,7 @@ sub report_edit : Path('report_edit') : Args(1) { $c->forward( 'log_edit', [ $id, 'problem', 'resend' ] ); } elsif ( $c->get_param('mark_sent') ) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); $problem->whensent(\'current_timestamp'); $problem->update(); $c->stash->{status_message} = '<p><em>' . _('That problem has been marked as sent.') . '</em></p>'; @@ -717,7 +717,7 @@ sub report_edit : Path('report_edit') : Args(1) { $c->forward('ban_user'); } elsif ( $c->get_param('submit') ) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my $done = 0; my $edited = 0; @@ -917,7 +917,7 @@ sub users: Path('users') : Args(0) { } } else { - $c->forward('get_token'); + $c->forward('/auth/get_csrf_token'); $c->forward('fetch_all_bodies'); # Admin users by default @@ -942,7 +942,7 @@ sub update_edit : Path('update_edit') : Args(1) { $c->detach( '/page_error_404_not_found' ) unless $update; - $c->forward('get_token'); + $c->forward('/auth/get_csrf_token'); $c->stash->{update} = $update; @@ -965,7 +965,7 @@ sub update_edit : Path('update_edit') : Args(1) { $c->stash->{update}->discard_changes; } elsif ( $c->get_param('submit') ) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my $old_state = $update->state; my $new_state = $c->get_param('state'); @@ -1047,12 +1047,12 @@ sub user_add : Path('user_edit') : Args(0) { my ( $self, $c ) = @_; $c->stash->{template} = 'admin/user_edit.html'; - $c->forward('get_token'); + $c->forward('/auth/get_csrf_token'); $c->forward('fetch_all_bodies'); return unless $c->get_param('submit'); - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); unless ($c->get_param('email')) { $c->stash->{field_errors}->{email} = _('Please enter a valid email'); @@ -1084,7 +1084,7 @@ sub user_add : Path('user_edit') : Args(0) { sub user_edit : Path('user_edit') : Args(1) { my ( $self, $c, $id ) = @_; - $c->forward('get_token'); + $c->forward('/auth/get_csrf_token'); my $user = $c->model('DB::User')->find( { id => $id } ); $c->stash->{user} = $user; @@ -1092,7 +1092,7 @@ sub user_edit : Path('user_edit') : Args(1) { $c->forward('fetch_all_bodies'); if ( $c->get_param('submit') ) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my $edited = 0; @@ -1328,40 +1328,6 @@ sub get_user : Private { return $user; } -=item get_token - -Generate a token based on user and secret - -=cut - -sub get_token : Private { - my ( $self, $c ) = @_; - - my $secret = $c->model('DB::Secret')->get; - my $user = $c->forward('get_user'); - my $token = sha1_hex($user . $secret); - $c->stash->{token} = $token; - - return 1; -} - -=item check_token - -Check that a token has been set on a request and it's the correct token. If -not then display 404 page - -=cut - -sub check_token : Private { - my ( $self, $c ) = @_; - - if ( !$c->get_param('token') || $c->get_param('token') ne $c->stash->{token} ) { - $c->detach( '/page_error_404_not_found' ); - } - - return 1; -} - =item log_edit $c->forward( 'log_edit', [ $object_id, $object_type, $action_performed ] ); diff --git a/perllib/FixMyStreet/App/Controller/Alert.pm b/perllib/FixMyStreet/App/Controller/Alert.pm index ddda02abd..b578fbbcc 100644 --- a/perllib/FixMyStreet/App/Controller/Alert.pm +++ b/perllib/FixMyStreet/App/Controller/Alert.pm @@ -36,6 +36,8 @@ sub index : Path('') : Args(0) { sub list : Path('list') : Args(0) { my ( $self, $c ) = @_; + $c->forward('/auth/get_csrf_token'); + return unless $c->forward('setup_request') && $c->forward('prettify_pc') @@ -112,6 +114,8 @@ Sign up to email alerts sub subscribe_email : Private { my ( $self, $c ) = @_; + $c->forward('/auth/check_csrf_token'); + $c->stash->{errors} = []; $c->forward('process_user'); @@ -146,6 +150,8 @@ sub subscribe_email : Private { sub updates : Path('updates') : Args(0) { my ( $self, $c ) = @_; + $c->forward('/auth/get_csrf_token'); + $c->stash->{email} = $c->get_param('rznvy'); $c->stash->{problem_id} = $c->get_param('id'); } diff --git a/perllib/FixMyStreet/App/Controller/Around.pm b/perllib/FixMyStreet/App/Controller/Around.pm index b0340204a..b8f038ce3 100644 --- a/perllib/FixMyStreet/App/Controller/Around.pm +++ b/perllib/FixMyStreet/App/Controller/Around.pm @@ -156,6 +156,8 @@ sub display_location : Private { # set the template to use $c->stash->{template} = 'around/display_location.html'; + $c->forward('/auth/get_csrf_token'); + # get the lat,lng my $latitude = $c->stash->{latitude}; my $longitude = $c->stash->{longitude}; diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index c5a6cf9bf..be95040e1 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -6,8 +6,9 @@ BEGIN { extends 'Catalyst::Controller'; } use Email::Valid; use Net::Domain::TLD; -use mySociety::AuthToken; +use Digest::HMAC_SHA1 qw(hmac_sha1); use JSON::MaybeXS; +use MIME::Base64; use Net::Facebook::Oauth2; use Net::Twitter::Lite::WithAPIv1_1; @@ -37,16 +38,17 @@ sub general : Path : Args(0) { # all done unless we have a form posted to us return unless $c->req->method eq 'POST'; - # decide which action to take - $c->detach('facebook_sign_in') if $c->get_param('facebook_sign_in'); - $c->detach('twitter_sign_in') if $c->get_param('twitter_sign_in'); - - my $clicked_password = $c->get_param('sign_in'); my $clicked_email = $c->get_param('email_sign_in'); + my $data_address = $c->get_param('email'); my $data_password = $c->get_param('password_sign_in'); my $data_email = $c->get_param('name') || $c->get_param('password_register'); + # decide which action to take $c->detach('email_sign_in') if $clicked_email || ($data_email && !$data_password); + if (!$data_address && !$data_password && !$data_email) { + $c->detach('facebook_sign_in') if $c->get_param('facebook_sign_in'); + $c->detach('twitter_sign_in') if $c->get_param('twitter_sign_in'); + } $c->forward( 'sign_in' ) && $c->detach( 'redirect_on_signin', [ $c->get_param('r') ] ); @@ -83,6 +85,9 @@ sub sign_in : Private { $c->set_session_cookie_expire(0) unless $remember_me; + # Regenerate CSRF token as session ID changed + $c->forward('get_csrf_token'); + return 1; } @@ -414,12 +419,13 @@ sub change_password : Local { $c->detach( 'redirect' ) unless $c->user; - # FIXME - CSRF check here - # FIXME - minimum criteria for passwords (length, contain number, etc) + $c->forward('get_csrf_token'); # If not a post then no submission return unless $c->req->method eq 'POST'; + $c->forward('check_csrf_token'); + # get the passwords my $new = $c->get_param('new_password') // ''; my $confirm = $c->get_param('confirm') // ''; @@ -443,6 +449,38 @@ sub change_password : Local { } +sub get_csrf_token : Private { + my ( $self, $c ) = @_; + + my $time = $c->stash->{csrf_time} || time(); + my $hash = hmac_sha1("$time-" . ($c->sessionid || ""), $c->model('DB::Secret')->get); + $hash = encode_base64($hash, ""); + $hash =~ s/=$//; + my $token = "$time-$hash"; + $c->stash->{csrf_token} = $token unless $c->stash->{csrf_time}; + return $token; +} + +sub check_csrf_token : Private { + my ( $self, $c ) = @_; + + my $token = $c->get_param('token') || ""; + $token =~ s/ /+/g; + my ($time) = $token =~ /^(\d+)-[0-9a-zA-Z+\/]+$/; + $c->stash->{csrf_time} = $time; + $c->detach('no_csrf_token') + unless $time + && $time > time() - 3600 + && $token eq $c->forward('get_csrf_token'); + delete $c->stash->{csrf_time}; +} + +sub no_csrf_token : Private { + my ($self, $c) = @_; + $c->stash->{message} = _('Unknown error'); + $c->stash->{template} = 'errors/generic.html'; +} + =head2 sign_out Log the user out. Tell them we've done so. diff --git a/perllib/FixMyStreet/App/Controller/Moderate.pm b/perllib/FixMyStreet/App/Controller/Moderate.pm index 77a3346dc..2d23417b9 100644 --- a/perllib/FixMyStreet/App/Controller/Moderate.pm +++ b/perllib/FixMyStreet/App/Controller/Moderate.pm @@ -57,6 +57,8 @@ sub report : Chained('moderate') : PathPart('report') : CaptureArgs(1) { $c->detach unless $c->user_exists; $c->detach unless $c->user->has_permission_to(moderate => $problem->bodies_str); + $c->forward('/auth/check_csrf_token'); + my $original = $problem->find_or_new_related( moderation_original_data => { title => $problem->title, detail => $problem->detail, diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index b3e546c2c..89df4a52d 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -72,6 +72,7 @@ sub ajax : Path('ajax') : Args(1) { sub _display : Private { my ( $self, $c, $id ) = @_; + $c->forward('/auth/get_csrf_token'); $c->forward( 'load_problem_or_display_error', [ $id ] ); $c->forward( 'load_updates' ); $c->forward( 'format_problem_for_display' ); @@ -249,6 +250,8 @@ users too about this change, at which point we can delete: sub delete :Local :Args(1) { my ( $self, $c, $id ) = @_; + $c->forward('/auth/check_csrf_token'); + $c->forward( 'load_problem_or_display_error', [ $id ] ); my $p = $c->stash->{problem}; diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm index 76098c119..b5d4cba3f 100644 --- a/perllib/FixMyStreet/App/Controller/Report/New.pm +++ b/perllib/FixMyStreet/App/Controller/Report/New.pm @@ -81,10 +81,12 @@ sub report_new : Path : Args(0) { # create the report - loading a partial if available $c->forward('initialize_report'); + $c->forward('/auth/get_csrf_token'); # work out the location for this report and do some checks + # Also show map if we're just updating the filters return $c->forward('redirect_to_around') - unless $c->forward('determine_location'); + if $c->get_param('filter_update') || !$c->forward('determine_location'); # create a problem from the submitted details $c->stash->{template} = "report/new/fill_in_details.html"; @@ -95,6 +97,7 @@ sub report_new : Path : Args(0) { # deal with the user and report and check both are happy return unless $c->forward('check_form_submitted'); + $c->forward('/auth/check_csrf_token'); $c->forward('process_user'); $c->forward('process_report'); $c->forward('/photo/process_photo'); @@ -1229,10 +1232,12 @@ sub redirect_to_around : Private { my ( $self, $c ) = @_; my $params = { - pc => ( $c->stash->{pc} || $c->get_param('pc') || '' ), lat => $c->stash->{latitude}, lon => $c->stash->{longitude}, }; + foreach (qw(pc zoom status filter_category)) { + $params->{$_} = $c->get_param($_); + } # delete empty values for ( keys %$params ) { diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm index 275a300bd..d03797f56 100644 --- a/perllib/FixMyStreet/App/Controller/Report/Update.pm +++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm @@ -25,6 +25,7 @@ sub report_update : Path : Args(0) { $c->forward('check_form_submitted') or $c->go( '/report/display', [ $c->stash->{problem}->id ] ); + $c->forward('/auth/check_csrf_token'); $c->forward('process_update'); $c->forward('process_user'); $c->forward('/photo/process_photo'); diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index 987f0bb67..2e4a167db 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -541,7 +541,7 @@ sub admin_report_edit { # If super or dm check that the token is correct before proceeding if ( ($type eq 'super' || $type eq 'dm') && $c->get_param('submit') ) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); } # All types of users can add internal notes @@ -807,7 +807,7 @@ sub admin_report_edit { # subdivision, or because the customer was not contactable. # We handle these in the same way but with different statuses. - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my $not_contactable = $c->get_param('not_contactable'); @@ -829,7 +829,7 @@ sub admin_report_edit { $self->update_admin_log($c, $problem); $c->res->redirect( '/admin/summary' ); } elsif ($c->get_param('submit')) { - $c->forward('check_token'); + $c->forward('/auth/check_csrf_token'); my $db_update = 0; if ( $c->get_param('latitude') != $problem->latitude || $c->get_param('longitude') != $problem->longitude ) { diff --git a/perllib/FixMyStreet/Email.pm b/perllib/FixMyStreet/Email.pm index d4bfee14e..ce7dad47a 100644 --- a/perllib/FixMyStreet/Email.pm +++ b/perllib/FixMyStreet/Email.pm @@ -11,7 +11,6 @@ use Encode; use POSIX qw(); use Template; use Digest::HMAC_SHA1 qw(hmac_sha1_hex); -use Text::Wrap; use mySociety::Locale; use mySociety::Random qw(random_bytes); use Utils::Email; @@ -188,13 +187,7 @@ sub construct_email ($) { # regex means, "replace any line ending that is neither preceded (?<!\n) # nor followed (?!\n) by a blank line with a single space". $body =~ s#(?<!\n)(?<! )\n(?!\n)# #gs; - - # Wrap text to 72-column lines. - local($Text::Wrap::columns) = 69; - local($Text::Wrap::huge) = 'overflow'; - local($Text::Wrap::unexpand) = 0; - $body = Text::Wrap::wrap('', '', $body); - $body =~ s/^\s+$//mg; # Do it again because of wordwrapping indented lines + $body =~ s# +$##mg; $p->{Subject} = $subject if defined($subject); diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t index 777d733e2..06932f70a 100644 --- a/t/app/controller/alert_new.t +++ b/t/app/controller/alert_new.t @@ -7,6 +7,10 @@ use FixMyStreet::App; my $mech = FixMyStreet::TestMech->new; +$mech->log_in_ok('test@example.com'); +$mech->get_ok('/alert/subscribe?id=1'); +my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/; + foreach my $test ( { email => 'test@example.com', @@ -71,7 +75,7 @@ foreach my $test ( $mech->delete_user($user); } - $mech->get_ok( $test->{uri} ); + $mech->get_ok( $test->{uri} . "&token=$csrf" ); $mech->content_contains( $test->{content} ); $user = @@ -113,7 +117,7 @@ foreach my $test ( my $existing_id = $alert->id; my $existing_token = $url_token; - $mech->get_ok( $test->{uri} ); + $mech->get_ok( $test->{uri} . "&token=$csrf" ); $email = $mech->get_email; ok $email, 'got a second email'; @@ -165,7 +169,7 @@ foreach my $test ( # clear existing data so we can be sure we're creating it ok $alert->delete() if $alert && !$test->{exist}; - $mech->get_ok( '/alert/subscribe?type=local&rznvy=test-new@example.com&feed=area:1000:A_Location' ); + $mech->get_ok( '/alert/subscribe?type=local&rznvy=test-new@example.com&feed=area:1000:A_Location&token=' . $csrf ); $alert = FixMyStreet::App->model('DB::Alert')->find( { @@ -262,7 +266,7 @@ for my $test ( FixMyStreet::App->model('DB::Abuse') ->find_or_create( { email => $test->{email} } ); - $mech->get_ok( $test->{uri} ); + $mech->get_ok( $test->{uri} . "&token=$csrf" ); $mech->content_contains( $test->{content} ); $user = diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t index 235a3af7e..9b3d9468a 100644 --- a/t/app/controller/auth.t +++ b/t/app/controller/auth.t @@ -128,7 +128,7 @@ $mech->not_logged_in_ok; ok my $form = $mech->form_name('change_password'), "found change password form"; is_deeply [ sort grep { $_ } map { $_->name } $form->inputs ], # - [ 'confirm', 'new_password' ], + [ 'confirm', 'new_password', 'token' ], "check we got expected fields (ie not old_password)"; # check the various ways the form can be wrong diff --git a/t/app/controller/moderate.t b/t/app/controller/moderate.t index b79f50e73..38216c708 100644 --- a/t/app/controller/moderate.t +++ b/t/app/controller/moderate.t @@ -8,6 +8,7 @@ use FixMyStreet::App; use Data::Dumper; my $mech = FixMyStreet::TestMech->new; +$mech->host('www.example.org'); my $BROMLEY_ID = 2482; my $body = $mech->create_body_ok( $BROMLEY_ID, 'Bromley Council' ); @@ -92,11 +93,12 @@ my %problem_prepopulated = ( subtest 'Problem moderation' => sub { subtest 'Post modify title and text' => sub { - $mech->post_ok('/moderate/report/' . $report->id, { + $mech->get_ok($REPORT_URL); + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_title => 'Good good', problem_detail => 'Good good improved', - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $report->discard_changes; @@ -105,11 +107,11 @@ subtest 'Problem moderation' => sub { }; subtest 'Revert title and text' => sub { - $mech->post_ok('/moderate/report/' . $report->id, { + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_revert_title => 1, problem_revert_detail => 1, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $report->discard_changes; @@ -120,18 +122,18 @@ subtest 'Problem moderation' => sub { subtest 'Make anonymous' => sub { $mech->content_lacks('Reported anonymously'); - $mech->post_ok('/moderate/report/' . $report->id, { + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_show_name => 0, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $mech->content_contains('Reported anonymously'); - $mech->post_ok('/moderate/report/' . $report->id, { + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_show_name => 1, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $mech->content_lacks('Reported anonymously'); @@ -140,18 +142,18 @@ subtest 'Problem moderation' => sub { subtest 'Hide photo' => sub { $mech->content_contains('Photo of this report'); - $mech->post_ok('/moderate/report/' . $report->id, { + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_show_photo => 0, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $mech->content_lacks('Photo of this report'); - $mech->post_ok('/moderate/report/' . $report->id, { + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_show_photo => 1, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $mech->content_contains('Photo of this report'); @@ -160,10 +162,10 @@ subtest 'Problem moderation' => sub { subtest 'Hide report' => sub { $mech->clear_emails_ok; - my $resp = $mech->post('/moderate/report/' . $report->id, { + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_hide => 1, - }); + }}); $mech->base_unlike( qr{/report/}, 'redirected to front page' ); $report->discard_changes; @@ -185,22 +187,23 @@ $mech->content_lacks('Posted anonymously', 'sanity check'); subtest 'Problem 2' => sub { my $REPORT2_URL = '/report/' . $report2->id ; - $mech->post_ok('/moderate/report/' . $report2->id, { + $mech->get_ok($REPORT2_URL); + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_title => 'Good good', problem_detail => 'Good good improved', - }); + }}); $mech->base_like( qr{\Q$REPORT2_URL\E} ); $report2->discard_changes; is $report2->title, 'Good [...] good'; is $report2->detail, 'Good [...] good [...]improved'; - $mech->post_ok('/moderate/report/' . $report2->id, { + $mech->submit_form_ok({ with_fields => { %problem_prepopulated, problem_revert_title => 1, problem_revert_detail => 1, - }); + }}); $mech->base_like( qr{\Q$REPORT2_URL\E} ); $report2->discard_changes; @@ -229,13 +232,12 @@ my $update = create_update(); subtest 'updates' => sub { - my $MODERATE_UPDATE_URL = sprintf '/moderate/report/%d/update/%d', $report->id, $update->id; - subtest 'Update modify text' => sub { - $mech->post_ok( $MODERATE_UPDATE_URL, { + $mech->get_ok($REPORT_URL); + $mech->submit_form_ok({ with_fields => { %update_prepopulated, update_detail => 'update good good good', - }) or die $mech->content; + }}) or die $mech->content; $mech->base_like( qr{\Q$REPORT_URL\E} ); $update->discard_changes; @@ -243,10 +245,10 @@ subtest 'updates' => sub { }; subtest 'Revert text' => sub { - $mech->post_ok( $MODERATE_UPDATE_URL, { + $mech->submit_form_ok({ with_fields => { %update_prepopulated, update_revert_detail => 1, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $update->discard_changes; @@ -258,18 +260,18 @@ subtest 'updates' => sub { $mech->content_lacks('Posted anonymously') or die sprintf '%d (%d)', $update->id, $report->comments->count; - $mech->post_ok( $MODERATE_UPDATE_URL, { + $mech->submit_form_ok({ with_fields => { %update_prepopulated, update_show_name => 0, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $mech->content_contains('Posted anonymously'); - $mech->post_ok( $MODERATE_UPDATE_URL, { + $mech->submit_form_ok({ with_fields => { %update_prepopulated, update_show_name => 1, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $mech->content_lacks('Posted anonymously'); @@ -283,18 +285,18 @@ subtest 'updates' => sub { $mech->content_contains('Photo of this report') or die $mech->content; - $mech->post_ok( $MODERATE_UPDATE_URL, { + $mech->submit_form_ok({ with_fields => { %update_prepopulated, update_show_photo => 0, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $mech->content_lacks('Photo of this report'); - $mech->post_ok( $MODERATE_UPDATE_URL, { + $mech->submit_form_ok({ with_fields => { %update_prepopulated, update_show_photo => 1, - }); + }}); $mech->base_like( qr{\Q$REPORT_URL\E} ); $mech->content_contains('Photo of this report'); @@ -303,10 +305,10 @@ subtest 'updates' => sub { subtest 'Hide comment' => sub { $mech->content_contains('update good good bad good'); - $mech->post_ok( $MODERATE_UPDATE_URL, { + $mech->submit_form_ok({ with_fields => { %update_prepopulated, update_hide => 1, - }); + }}); $mech->content_lacks('update good good bad good'); }; @@ -316,11 +318,11 @@ subtest 'updates' => sub { my $update2 = create_update(); subtest 'Update 2' => sub { - my $MODERATE_UPDATE2_URL = sprintf '/moderate/report/%d/update/%d', $report->id, $update2->id; - $mech->post_ok( $MODERATE_UPDATE2_URL, { + $mech->get_ok($REPORT_URL); + $mech->submit_form_ok({ with_fields => { %update_prepopulated, update_detail => 'update good good good', - }) or die $mech->content; + }}) or die $mech->content; $update2->discard_changes; is $update2->text, 'update good good [...] good', diff --git a/t/app/controller/photo.t b/t/app/controller/photo.t index 425e3c4df..a065c7732 100644 --- a/t/app/controller/photo.t +++ b/t/app/controller/photo.t @@ -40,11 +40,15 @@ subtest "Check multiple upload worked" => sub { # submit the main form # can't post_ok as we lose the Content_Type header # (TODO rewrite with HTTP::Request::Common and request_ok) + $mech->get_ok('/report/new?lat=53.4031156&lon=-2.9840579'); + my ($csrf) = $mech->content =~ /name="token" value="([^"]*)"/; + $mech->post( '/report/new', Content_Type => 'form-data', Content => { submit_problem => 1, + token => $csrf, title => 'Test', lat => 53.4031156, lon => -2.9840579, # in Liverpool pc => 'L1 4LN', @@ -57,20 +61,17 @@ subtest "Check multiple upload worked" => sub { email => 'test@example.com', phone => '', category => 'Street lighting', - #password_sign_in => '', - #password_register => '', - #remember_me => undef, } ); ok $mech->success, 'Made request with multiple photo upload'; $mech->base_is('http://localhost/report/new'); $mech->content_like( - qr[(<img align="right" src="/photo/temp.1cdd4329ceee2234bd4e89cb33b42061a0724687.jpeg" alt="">\s*){3}], + qr[(<img align="right" src="/photo/temp.7f09ef2c3933731d47121fee1b8038b3fdd3bc77.jpeg" alt="">\s*){3}], 'Three uploaded pictures are all shown, safe'); $mech->content_contains( - 'name="upload_fileid" value="1cdd4329ceee2234bd4e89cb33b42061a0724687.jpeg,1cdd4329ceee2234bd4e89cb33b42061a0724687.jpeg,1cdd4329ceee2234bd4e89cb33b42061a0724687.jpeg"', + 'name="upload_fileid" value="7f09ef2c3933731d47121fee1b8038b3fdd3bc77.jpeg,7f09ef2c3933731d47121fee1b8038b3fdd3bc77.jpeg,7f09ef2c3933731d47121fee1b8038b3fdd3bc77.jpeg"', 'Returned upload_fileid contains expected hash, 3 times'); - my $image_file = path($UPLOAD_DIR, '1cdd4329ceee2234bd4e89cb33b42061a0724687.jpeg'); + my $image_file = path($UPLOAD_DIR, '7f09ef2c3933731d47121fee1b8038b3fdd3bc77.jpeg'); ok $image_file->exists, 'File uploaded to temp'; }; }; diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t index eb29d37da..ba550193e 100644 --- a/t/app/controller/report_new.t +++ b/t/app/controller/report_new.t @@ -701,6 +701,7 @@ subtest "test password errors for a user who is signing in as they report" => su subtest "test report creation for a user who is signing in as they report" => sub { $mech->log_out_ok; + $mech->cookie_jar({}); $mech->clear_emails_ok; # check that the user does not exist diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t index 7b4bf7854..2a3c7c0b3 100644 --- a/t/app/controller/report_updates.t +++ b/t/app/controller/report_updates.t @@ -510,20 +510,14 @@ subtest 'check non authority user cannot change set state' => sub { $user->update; $mech->get_ok("/report/$report_id"); - $mech->post_ok( "/report/update", { - submit_update => 1, - id => $report_id, - name => $user->name, - may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', - update => 'this is a forbidden update', - state => 'fixed - council', + $mech->submit_form_ok( { + form_id => 'form_update_form', + fields => { + may_show_name => 1, + update => 'this is a forbidden update', + state => 'fixed - council', }, - 'submitted with state', - ); + }, 'submitted with state'); is $mech->uri->path, "/report/update", "at /report/update"; @@ -540,20 +534,14 @@ for my $state ( qw/unconfirmed hidden partial/ ) { $user->update; $mech->get_ok("/report/$report_id"); - $mech->post_ok( "/report/update", { - submit_update => 1, - id => $report_id, - name => $user->name, - may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', - update => 'this is a forbidden update', - state => $state, + $mech->submit_form_ok( { + form_id => 'form_update_form', + fields => { + may_show_name => 1, + update => 'this is a forbidden update', + state => $state, }, - 'submitted with state', - ); + }, 'submitted with state'); is $mech->uri->path, "/report/update", "at /report/update"; @@ -570,10 +558,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to investigating', state => 'investigating', }, @@ -584,10 +568,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to in progress', state => 'in progress', }, @@ -598,10 +578,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to fixed', state => 'fixed', }, @@ -612,10 +588,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to action scheduled', state => 'action scheduled', }, @@ -626,10 +598,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to unable to fix', state => 'unable to fix', }, @@ -640,10 +608,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to internal referral', state => 'internal referral', }, @@ -655,10 +619,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to not responsible', state => 'not responsible', }, @@ -670,10 +630,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to duplicate', state => 'duplicate', }, @@ -685,10 +641,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to internal referral', state => 'internal referral', }, @@ -700,10 +652,6 @@ for my $test ( fields => { name => $user->name, may_show_name => 1, - add_alert => undef, - photo1 => '', - photo2 => '', - photo3 => '', update => 'Set state to fixed', state => 'fixed', }, diff --git a/t/app/controller/sample.jpg b/t/app/controller/sample.jpg Binary files differindex 23198cb83..4930821c4 100644 --- a/t/app/controller/sample.jpg +++ b/t/app/controller/sample.jpg diff --git a/t/app/helpers/send_email_sample.txt b/t/app/helpers/send_email_sample.txt index 87604008c..68fe61f0e 100644 --- a/t/app/helpers/send_email_sample.txt +++ b/t/app/helpers/send_email_sample.txt @@ -14,13 +14,13 @@ utf8: =E6=88=91=E4=BB=AC=E5=BA=94=E8=AF=A5=E8=83=BD=E5=A4=9F=E6=97=A0=E7=BC= indented_text -long line: Lorem ipsum dolor sit amet, consectetur adipisicing elit, -sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. -Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris -nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in -reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla -pariatur. Excepteur sint occaecat cupidatat non proident, sunt in -culpa qui officia deserunt mollit anim id est laborum. +long line: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do= + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad min= +im veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea = +commodo consequat. Duis aute irure dolor in reprehenderit in voluptate veli= +t esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupi= +datat non proident, sunt in culpa qui officia deserunt mollit anim id est l= +aborum. -Yours,=20=20 +Yours, FixMyStreet.= diff --git a/t/app/helpers/send_email_sample_mime.txt b/t/app/helpers/send_email_sample_mime.txt index 1747204f7..7b4ce91f6 100644 --- a/t/app/helpers/send_email_sample_mime.txt +++ b/t/app/helpers/send_email_sample_mime.txt @@ -19,15 +19,15 @@ utf8: =E6=88=91=E4=BB=AC=E5=BA=94=E8=AF=A5=E8=83=BD=E5=A4=9F=E6=97=A0=E7=BC= indented_text
-long line: Lorem ipsum dolor sit amet, consectetur adipisicing elit,
-sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
-nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
-reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
-pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
-culpa qui officia deserunt mollit anim id est laborum.
-
-Yours,=20=20
+long line: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do=
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad min=
+im veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea =
+commodo consequat. Duis aute irure dolor in reprehenderit in voluptate veli=
+t esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupi=
+datat non proident, sunt in culpa qui officia deserunt mollit anim id est l=
+aborum.
+
+Yours,
FixMyStreet.=
--BOUNDARY
diff --git a/t/app/model/photoset.t b/t/app/model/photoset.t index 577e39eb1..f0fc601e2 100644 --- a/t/app/model/photoset.t +++ b/t/app/model/photoset.t @@ -58,7 +58,7 @@ subtest 'Photoset with photo inline in DB' => sub { my $report = make_report( $image_path->slurp ); my $photoset = $report->get_photoset(); is $photoset->num_images, 1, 'Found just 1 image'; - is $photoset->data, '1cdd4329ceee2234bd4e89cb33b42061a0724687.jpeg'; + is $photoset->data, '7f09ef2c3933731d47121fee1b8038b3fdd3bc77.jpeg'; }; $image_path->copy( path( $UPLOAD_DIR, '0123456789012345678901234567890123456789.jpeg' ) ); diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t index cf66136e5..a595f48c9 100644 --- a/t/cobrand/zurich.t +++ b/t/cobrand/zurich.t @@ -810,17 +810,12 @@ subtest "photo must be supplied for categories that require it" => sub { MAPIT_ID_WHITELIST => [ 423017 ], MAP_TYPE => 'Zurich,OSM', }, sub { - $mech->post_ok( '/report/new', { + $mech->get_ok('/report/new?lat=47.381817&lon=8.529156'); + $mech->submit_form_ok({ with_fields => { detail => 'Problem-Bericht', - lat => 47.381817, - lon => 8.529156, email => 'user@example.org', - pc => '', - name => '', category => 'Graffiti - photo required', - photo => '', - submit_problem => 1, - }); + }}); is $mech->res->code, 200, "missing photo shouldn't return anything but 200"; $mech->content_contains(_("Photo is required."), 'response should contain photo error message'); }; diff --git a/t/cobrand/zurich_attachments.txt b/t/cobrand/zurich_attachments.txt index bdc4333bf..bf8d6872b 100644 --- a/t/cobrand/zurich_attachments.txt +++ b/t/cobrand/zurich_attachments.txt @@ -14,7 +14,7 @@ Gr=C3=BCezi External Body, =C3=96ffentliche URL: http://www.example.org/report/REPORT_ID
-Bei Fragen zu "Z=C3=BCri wie neu" wenden Sie sich bitte an
+Bei Fragen zu "Z=C3=BCri wie neu" wenden Sie sich bitte an =
gis-zentrum@zuerich.ch.=
--BOUNDARY
diff --git a/t/open311/getservicerequestupdates.t b/t/open311/getservicerequestupdates.t index 134d5422e..4afac7182 100644 --- a/t/open311/getservicerequestupdates.t +++ b/t/open311/getservicerequestupdates.t @@ -388,7 +388,7 @@ subtest 'Update with media_url includes image in update' => sub { is $problem->comments->count, 1, 'comment count'; my $c = $problem->comments->first; is $c->external_id, 638344; - is $c->photo, '1cdd4329ceee2234bd4e89cb33b42061a0724687.jpeg', 'photo exists'; + is $c->photo, '7f09ef2c3933731d47121fee1b8038b3fdd3bc77.jpeg', 'photo exists'; }; foreach my $test ( diff --git a/templates/email/fixmystreet/signature.txt b/templates/email/fixmystreet/signature.txt index 14b7d83e7..834e69b9d 100644 --- a/templates/email/fixmystreet/signature.txt +++ b/templates/email/fixmystreet/signature.txt @@ -2,7 +2,7 @@ All the best, The FixMyStreet team -https://www.FixMyStreet.com +https://www.FixMyStreet.com Twitter: https://twitter.com/FixMyStreet Facebook: http://www.facebook.com/fixmystreet diff --git a/templates/web/base/admin/body-form.html b/templates/web/base/admin/body-form.html index 7acfbfdd5..8c4956f7f 100644 --- a/templates/web/base/admin/body-form.html +++ b/templates/web/base/admin/body-form.html @@ -236,7 +236,7 @@ <p> <input type="hidden" name="posted" value="body"> - <input type="hidden" name="token" value="[% token %]"> + <input type="hidden" name="token" value="[% csrf_token %]"> <input type="submit" value="[% body ? loc('Update body') : loc('Add body') %]"> </p> </form> diff --git a/templates/web/base/admin/body.html b/templates/web/base/admin/body.html index d5e575666..15802fc44 100644 --- a/templates/web/base/admin/body.html +++ b/templates/web/base/admin/body.html @@ -97,7 +97,7 @@ <p> <input type="hidden" name="posted" value="update"> - <input type="hidden" name="token" value="[% token %]"> + <input type="hidden" name="token" value="[% csrf_token %]"> <input type="submit" name="Update statuses" value="[% loc('Update statuses') %]"> </p> </form> @@ -202,7 +202,7 @@ <p> <input type="hidden" name="posted" value="new" > - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="submit" name="Create category" value="[% errors ? loc('Save changes') : loc('Create category') %]" > </p> diff --git a/templates/web/base/admin/category_edit.html b/templates/web/base/admin/category_edit.html index c0bd43ef5..6537fe028 100644 --- a/templates/web/base/admin/category_edit.html +++ b/templates/web/base/admin/category_edit.html @@ -22,7 +22,7 @@ <form method="post" action="[% c.uri_for('body', body_id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> <p><strong>[% loc('Category:') %] </strong>[% contact.category | html %] <input type="hidden" name="category" value="[% contact.category | html %]" > - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > [% IF contact.extra %] <p><strong>[% loc('Extra data:') %] </strong> [% USE Dumper %] diff --git a/templates/web/base/admin/report_edit.html b/templates/web/base/admin/report_edit.html index c0cdead84..065c6c2ce 100644 --- a/templates/web/base/admin/report_edit.html +++ b/templates/web/base/admin/report_edit.html @@ -4,7 +4,7 @@ [% status_message %] <form method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="hidden" name="submit" value="1" > <ul> [%- cobrand_data = problem.cobrand_data; diff --git a/templates/web/base/admin/update_edit.html b/templates/web/base/admin/update_edit.html index a956bb2cb..06bee6010 100644 --- a/templates/web/base/admin/update_edit.html +++ b/templates/web/base/admin/update_edit.html @@ -4,7 +4,7 @@ [% status_message %] <form method="post" action="[% c.uri_for( 'update_edit', update.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="hidden" name="submit" value="1" > <ul> [%- cobrand_data = update.cobrand_data; diff --git a/templates/web/base/admin/user-form.html b/templates/web/base/admin/user-form.html index 3956e8533..b863bf96a 100644 --- a/templates/web/base/admin/user-form.html +++ b/templates/web/base/admin/user-form.html @@ -1,5 +1,5 @@ <form method="post" action="[% c.uri_for( 'user_edit', user.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="hidden" name="submit" value="1" > [% IF c.cobrand.moniker == 'zurich' AND field_errors.email %] diff --git a/templates/web/base/alert/_list.html b/templates/web/base/alert/_list.html index 395948248..f94ce84f8 100644 --- a/templates/web/base/alert/_list.html +++ b/templates/web/base/alert/_list.html @@ -1,3 +1,4 @@ + <input type="hidden" name="token" value="[% csrf_token %]"> <input type="hidden" name="type" value="local"> <input type="hidden" name="pc" value="[% pc | html %]"> <input type="hidden" name="latitude" value="[% latitude | html %]"> @@ -19,7 +20,7 @@ <p id="rss_local"> <input type="radio" name="feed" id="[% rss_feed_id %]" value="[% rss_feed_id %]"[% IF rss_feed_id == selected_feed || selected_feed == '' %] checked[% END %]> <label class="inline" for="[% rss_feed_id %]">[% tprintf( loc('Problems within %.1fkm of this location'), population_radius ) %]</label> - <a href='[% rss_feed_uri %]'><img src='/i/feed.png' width='16' height='16' title='[% loc('RSS feed of nearby problems') %]' alt='[% loc('RSS feed') %]' border='0'></a> + <a href="[% rss_feed_uri %]"><img src='/i/feed.png' width='16' height='16' title='[% loc('RSS feed of nearby problems') %]' alt='[% loc('RSS feed') %]' border='0'></a> <br /> [% loc('(a default distance which covers roughly 200,000 people)') %] </p> diff --git a/templates/web/base/alert/updates.html b/templates/web/base/alert/updates.html index 104bfa55a..ecaed37ca 100644 --- a/templates/web/base/alert/updates.html +++ b/templates/web/base/alert/updates.html @@ -23,6 +23,7 @@ <input class="green-btn" type="submit" value="[% loc('Subscribe') %]"> </div> + <input type="hidden" name="token" value="[% csrf_token %]"> <input type="hidden" name="id" value="[% problem_id | html %]"> <input type="hidden" name="type" value="updates"> </fieldset> diff --git a/templates/web/base/around/display_location.html b/templates/web/base/around/display_location.html index 7bf62e528..b2e578d3f 100755 --- a/templates/web/base/around/display_location.html +++ b/templates/web/base/around/display_location.html @@ -40,6 +40,7 @@ [% IF allow_creation %] <form action="[% c.uri_for('/report/new') %]" method="post" name="mapForm" id="mapForm" enctype="multipart/form-data" class="validate" novalidate> + <input type="hidden" name="token" value="[% csrf_token %]"> [% IF c.req.params.map_override %] <input type="hidden" name="map_override" value="[% c.req.params.map_override | html %]"> [% END %] @@ -54,16 +55,16 @@ <p id='sub_map_links'> [% map_sub_links %] [% IF c.req.params.no_pins %] - <a id='hide_pins_link' rel='nofollow' href='[% c.uri_with( { no_pins => 0 } ) %]'>[% loc('Show pins') %]</a> + <a id='hide_pins_link' rel='nofollow' href="[% c.uri_with( { no_pins => 0 } ) %]">[% loc('Show pins') %]</a> [% ELSE %] - <a id='hide_pins_link' rel='nofollow' href='[% c.uri_with( { no_pins => 1 } ) %]'>[% loc('Hide pins') %]</a> + <a id='hide_pins_link' rel='nofollow' href="[% c.uri_with( { no_pins => 1 } ) %]">[% loc('Hide pins') %]</a> [% END %] [% IF c.cobrand.country == 'GB' || c.cobrand.country == 'NO' %] <span class="hidden">|</span> [% IF c.req.params.all_pins %] - <a id='all_pins_link' rel='nofollow' href='[% c.uri_with( { no_pins => undef, all_pins => undef } ) %]'>[% loc('Hide old') %]</a> + <a id='all_pins_link' rel='nofollow' href="[% c.uri_with( { no_pins => undef, all_pins => undef } ) %]">[% loc('Hide old') %]</a> [% ELSE %] - <a id='all_pins_link' rel='nofollow' href='[% c.uri_with( { no_pins => undef, all_pins => 1 } ) %]'>[% loc('Show old') %]</a> + <a id='all_pins_link' rel='nofollow' href="[% c.uri_with( { no_pins => undef, all_pins => 1 } ) %]">[% loc('Show old') %]</a> [% END %] [% END %] </p> diff --git a/templates/web/base/auth/change_password.html b/templates/web/base/auth/change_password.html index b4170c23e..be0dc69b4 100644 --- a/templates/web/base/auth/change_password.html +++ b/templates/web/base/auth/change_password.html @@ -3,11 +3,12 @@ <h1>[% loc('Change password') %]</h1> [% IF password_changed %] - <p id="fixed">[% loc('Your password has been changed') %]</p> + <p class="form-success">[% loc('Your password has been changed') %]</p> [% END %] <form action="[% c.uri_for('change_password') %]" method="post" name="change_password" class="fieldset"> + <input type="hidden" name="token" value="[% csrf_token %]"> [% IF password_error; diff --git a/templates/web/base/auth/general.html b/templates/web/base/auth/general.html index 253dc26a1..a8bf8f1e0 100644 --- a/templates/web/base/auth/general.html +++ b/templates/web/base/auth/general.html @@ -86,8 +86,15 @@ <input class="green-btn" type="submit" name="sign_in" value="[% loc('Sign in') %]"> </div> - <input type="checkbox" id="remember_me" name="remember_me" value='1'[% ' checked' IF remember_me %]> - <label class="inline n" for="remember_me">[% loc('Keep me signed in on this computer') %]</label> + <div class="checkbox-group"> + <input type="checkbox" id="remember_me" name="remember_me" value='1'[% ' checked' IF remember_me %]> + <label class="inline n" for="remember_me">[% loc('Keep me signed in on this computer') %]</label> + </div> + + <div class="general-notes"> + <p><strong>[% loc('Forgotten your password?') %]</strong> + [% loc('Sign in by email instead, providing a new password. When you click the link in your email, your password will be updated.') %]</p> + </div> </div> [% END %] diff --git a/templates/web/base/header_opengraph.html b/templates/web/base/header_opengraph.html index f728d083f..6b2c8ff46 100644 --- a/templates/web/base/header_opengraph.html +++ b/templates/web/base/header_opengraph.html @@ -1,5 +1,5 @@ <meta property="og:url" content="[% c.cobrand.base_url %][% c.req.uri.path %]"> - <meta property="og:title" content="[% title || site_name %]"> + <meta property="og:title" content="[% title || site_name | html %]"> <meta property="og:site_name" content="[% site_name %]"> [% IF c.req.uri.path == '/' %]<meta property="og:description" content="Report, view, and discuss local street-related problems.">[% END %] <meta property="og:type" content="website"> diff --git a/templates/web/base/report/_main.html b/templates/web/base/report/_main.html index aaa167108..4821b3fa0 100644 --- a/templates/web/base/report/_main.html +++ b/templates/web/base/report/_main.html @@ -5,6 +5,7 @@ [% IF moderating %] [% original = problem_original %] <form method="post" action="/moderate/report/[% problem.id %]"> + <input type="hidden" name="token" value="[% csrf_token %]"> <p class="moderate-display"> <input type="button" class="btn moderate" value="moderate"> </p> diff --git a/templates/web/base/report/display_tools.html b/templates/web/base/report/display_tools.html index 004ae29e5..58e450c84 100644 --- a/templates/web/base/report/display_tools.html +++ b/templates/web/base/report/display_tools.html @@ -2,6 +2,7 @@ <ul id="key-tools"> [% IF c.user_exists AND c.cobrand.users_can_hide AND c.user.belongs_to_body( c.cobrand.council_id ) %] <li><form method="post" action="/report/delete/[% problem.id %]" id="remove-from-site-form"> + <input type="hidden" name="token" value="[% csrf_token %]"> <input type="submit" id="key-tool-report-abuse" class="abuse" value="Remove from site"> </form></li> [% ELSIF c.cobrand.moniker != 'zurich' %] @@ -30,16 +31,17 @@ <div id="report-updates-data" class="hidden-js"> <form action="[% c.uri_for( '/alert/subscribe' ) %]" method="post"> - <a href="[% c.uri_for( '/rss', problem.id ) %]"> + <p><a href="[% c.uri_for( '/rss', problem.id ) %]"> <img src="/i/feed.png" width="16" height="16" title="[% loc('RSS feed') %]" alt="[% loc('RSS feed of updates to this problem' ) %]" border="0"> </a> - <p>[% loc('Receive email when updates are left on this problem.' ) %]</p> + [% loc('Receive email when updates are left on this problem.' ) %]</p> <fieldset> <label class="hidden n" for="alert_rznvy">[% loc('Your email') %]</label> <div class="form-txt-submit-box"> <input type="email" name="rznvy" id="alert_rznvy" value="[% email | html %]" size="30" placeholder="[% loc('Your email') %]"> <input class="green-btn" type="submit" value="[% loc('Subscribe') %]"> </div> + <input type="hidden" name="token" value="[% csrf_token %]"> <input type="hidden" name="id" value="[% problem.id %]"> <input type="hidden" name="type" value="updates"> </fieldset> diff --git a/templates/web/base/report/new/fill_in_details.html b/templates/web/base/report/new/fill_in_details.html index 55b3a5207..d7e2f1d3a 100644 --- a/templates/web/base/report/new/fill_in_details.html +++ b/templates/web/base/report/new/fill_in_details.html @@ -12,16 +12,15 @@ <input type="hidden" name="map_override" value="[% c.req.params.map_override | html %]"> [% END %] - <input type="hidden" name="pc" value="[% pc | html %]"> - [% ELSE %] <form action="[% c.uri_for('/report/new') %]" method="post" name="mapSkippedForm"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %] class="validate"> - <input type="hidden" name="pc" value="[% pc | html %]"> <input type="hidden" name="skipped" value="1"> [% END %] + <input type="hidden" name="token" value="[% csrf_token %]"> + <input type="hidden" name="pc" value="[% pc | html %]"> <input type="hidden" name="latitude" id="fixmystreet.latitude" value="[% latitude | html %]"> <input type="hidden" name="longitude" id="fixmystreet.longitude" value="[% longitude | html %]"> diff --git a/templates/web/base/report/update-form.html b/templates/web/base/report/update-form.html index f6ce265bf..97e0df779 100644 --- a/templates/web/base/report/update-form.html +++ b/templates/web/base/report/update-form.html @@ -15,6 +15,7 @@ [% INCLUDE 'errors.html' %] <form method="post" action="[% c.uri_for( '/report/update' ) %]" id="form_update_form" name="updateForm" class="validate"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %]> + <input type="hidden" name="token" value="[% csrf_token %]"> <fieldset> [% IF NOT login_success AND NOT oauth_need_email %] [% INCLUDE 'report/update/form_update.html' %] diff --git a/templates/web/base/report/update.html b/templates/web/base/report/update.html index a09913d39..aaad33b7a 100644 --- a/templates/web/base/report/update.html +++ b/templates/web/base/report/update.html @@ -8,6 +8,7 @@ <li class="item-list__item item-list__item--updates"> [% IF moderating; original_update = update.moderation_original_data %] <form method="post" action="/moderate/report/[% problem.id %]/update/[% update.id %]"> + <input type="hidden" name="token" value="[% csrf_token %]"> <input type="button" class="btn moderate moderate-display" value="moderate"> <div class="moderate-edit"> <input type="checkbox" class="hide-document" name="update_hide"> diff --git a/templates/web/base/reports/_list-filters.html b/templates/web/base/reports/_list-filters.html index 4dd270dc6..d6f091aaa 100644 --- a/templates/web/base/reports/_list-filters.html +++ b/templates/web/base/reports/_list-filters.html @@ -25,7 +25,7 @@ <p class="report-list-filters"> [% tprintf(loc('<label>Show %s</label> <label>about %s</label>', 'The first %s is a dropdown of all/fixed/etc, the second is a dropdown of categories'), select_status, select_category) %] - <input type="submit" value="[% loc('Go') %]"> + <input type="submit" name="filter_update" value="[% loc('Go') %]"> </p> [% IF use_section_wrapper %] diff --git a/templates/web/bromley/report/display.html b/templates/web/bromley/report/display.html index da83e005f..27e1e64a9 100644 --- a/templates/web/bromley/report/display.html +++ b/templates/web/bromley/report/display.html @@ -56,6 +56,7 @@ [% INCLUDE 'errors.html' %] <form method="post" action="[% c.uri_for( '/report/update' ) %]" name="updateForm" class="validate"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %]> + <input type="hidden" name="token" value="[% csrf_token %]"> <fieldset> <input type="hidden" name="submit_update" value="1"> <input type="hidden" name="id" value="[% problem.id | html %]"> diff --git a/templates/web/eastsussex/report/update-form.html b/templates/web/eastsussex/report/update-form.html index e4fb47a45..b2c67890f 100644 --- a/templates/web/eastsussex/report/update-form.html +++ b/templates/web/eastsussex/report/update-form.html @@ -24,6 +24,7 @@ </p> <form method="post" action="/report/new"> + <input type="hidden" name="token" value="[% csrf_token %]"> <input type="hidden" name="latitude" value="[% problem.latitude %]"> <input type="hidden" name="longitude" value="[% problem.longitude %]"> <input type="submit" class="green-btn" value="CREATE A NEW PROBLEM NEARBY"> @@ -56,6 +57,7 @@ [% INCLUDE 'errors.html' %] <form method="post" action="[% c.uri_for( '/report/update' ) %]" id="form_update_form" name="updateForm" class="validate"[% IF c.cobrand.allow_photo_upload %] enctype="multipart/form-data"[% END %]> + <input type="hidden" name="token" value="[% csrf_token %]"> <fieldset> <input type="hidden" name="submit_update" value="1"> <input type="hidden" name="id" value="[% problem.id | html %]"> diff --git a/templates/web/seesomething/around/display_location.html b/templates/web/seesomething/around/display_location.html index b54311264..692ea22ee 100644 --- a/templates/web/seesomething/around/display_location.html +++ b/templates/web/seesomething/around/display_location.html @@ -20,6 +20,7 @@ %] <form action="[% c.uri_for('/report/new') %]" method="post" name="mapForm" id="mapForm" enctype="multipart/form-data" class="validate" novalidate> + <input type="hidden" name="token" value="[% csrf_token %]"> [% IF c.req.params.map_override %] <input type="hidden" name="map_override" value="[% c.req.params.map_override | html %]"> [% END %] diff --git a/templates/web/zurich/admin/body-form.html b/templates/web/zurich/admin/body-form.html index ac2887159..966bdf799 100644 --- a/templates/web/zurich/admin/body-form.html +++ b/templates/web/zurich/admin/body-form.html @@ -47,7 +47,7 @@ <p> <input type="hidden" name="posted" value="body"> - <input type="hidden" name="token" value="[% token %]"> + <input type="hidden" name="token" value="[% csrf_token %]"> <p> <input type="submit" value="[% body ? loc('Update body') : loc('Add body') %]"> </p> diff --git a/templates/web/zurich/admin/body.html b/templates/web/zurich/admin/body.html index 771f1e537..1a156773d 100644 --- a/templates/web/zurich/admin/body.html +++ b/templates/web/zurich/admin/body.html @@ -55,7 +55,7 @@ <p> <input type="hidden" name="posted" value="new" > - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="submit" name="Create category" value="[% errors ? loc('Save changes') : loc('Create category') %]"> </p> diff --git a/templates/web/zurich/admin/report_edit-sdm.html b/templates/web/zurich/admin/report_edit-sdm.html index 63c6b5e6f..e7602b659 100644 --- a/templates/web/zurich/admin/report_edit-sdm.html +++ b/templates/web/zurich/admin/report_edit-sdm.html @@ -11,7 +11,7 @@ </div> <form method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="hidden" name="submit" value="1" > <div class="admin-report-edit admin-report-edit--details"> diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html index dd876935c..f1ee7a846 100644 --- a/templates/web/zurich/admin/report_edit.html +++ b/templates/web/zurich/admin/report_edit.html @@ -13,7 +13,7 @@ [% pstate = problem.get_extra_metadata('closure_status') || problem.state %] <form id="report_edit" method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="hidden" name="submit" value="1" > <div class="admin-report-edit admin-report-edit--details"> diff --git a/templates/web/zurich/admin/template_edit.html b/templates/web/zurich/admin/template_edit.html index 1deda6a77..dbad55f08 100644 --- a/templates/web/zurich/admin/template_edit.html +++ b/templates/web/zurich/admin/template_edit.html @@ -25,7 +25,7 @@ <textarea name="text" class="required">[% rt.text |html %]</textarea> </p> <p> - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="submit" name="Edit templates" value="[% rt.id ? loc('Save changes') : loc('Create template') %]" > </p> [% IF rt.id %] diff --git a/templates/web/zurich/admin/update_edit.html b/templates/web/zurich/admin/update_edit.html index fbd96f3a5..adafff3a8 100644 --- a/templates/web/zurich/admin/update_edit.html +++ b/templates/web/zurich/admin/update_edit.html @@ -4,7 +4,7 @@ [% status_message %] <form method="post" action="[% c.uri_for( 'update_edit', update.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="token" value="[% csrf_token %]" > <input type="hidden" name="submit" value="1" > <ul> <li><a href="[% c.uri_for_email( '/report', update.problem_id ) %]#update_[% update.id %]">[% loc('View report on site' )%]</a></li> diff --git a/web/cobrands/eastsussex/layout.scss b/web/cobrands/eastsussex/layout.scss index 20be807a6..1f7c3bbb3 100644 --- a/web/cobrands/eastsussex/layout.scss +++ b/web/cobrands/eastsussex/layout.scss @@ -191,10 +191,6 @@ body.frontpage { width: auto; } -body.twothirdswidthpage .content aside { - box-shadow: 0 0 12px 0 #dae1e5; -} - .banner p#fixed { background-position: -328px -333px; } diff --git a/web/cobrands/fixmystreet.com/posters.scss b/web/cobrands/fixmystreet.com/posters.scss index ee8da9d32..518462539 100644 --- a/web/cobrands/fixmystreet.com/posters.scss +++ b/web/cobrands/fixmystreet.com/posters.scss @@ -129,7 +129,6 @@ body.goodies { padding: 0; aside { - box-shadow: none; background-color: inherit; } } diff --git a/web/cobrands/harrogate/layout.scss b/web/cobrands/harrogate/layout.scss index 417eff539..d8cc3b441 100644 --- a/web/cobrands/harrogate/layout.scss +++ b/web/cobrands/harrogate/layout.scss @@ -77,7 +77,6 @@ body.twothirdswidthpage .container .content { body.twothirdswidthpage .content aside { margin-top: 2em; - @include box-shadow(none); } diff --git a/web/cobrands/hart/layout.scss b/web/cobrands/hart/layout.scss index 99f8bdfcf..7799fa3fd 100644 --- a/web/cobrands/hart/layout.scss +++ b/web/cobrands/hart/layout.scss @@ -33,7 +33,6 @@ body.twothirdswidthpage .content { left: 672px; width: 208px; padding: 16px; - @include box-shadow(none); } .sticky-sidebar { left: 672px; @@ -43,7 +42,3 @@ body.twothirdswidthpage .content { } } } - -.content { - @include box-shadow(none); -} diff --git a/web/cobrands/oxfordshire/layout.scss b/web/cobrands/oxfordshire/layout.scss index 0bd37b95f..bc5c6c93a 100644 --- a/web/cobrands/oxfordshire/layout.scss +++ b/web/cobrands/oxfordshire/layout.scss @@ -34,24 +34,15 @@ body, body a { display: none; } -// White background, so no shadow or margin needed. -.content { +// White background, so no margin needed. +.content, +.iel8 .content { margin: 0; - @include box-shadow(none); -} -.iel8 { - .content { - margin: 0; - border: none; - } } // Fix location of aside sidebar body.twothirdswidthpage { .content { - aside { - @include box-shadow(none); - } .sticky-sidebar { aside { position: fixed; @@ -114,7 +105,7 @@ body.mappage { background-color: #069b01; // picked from header.jpg background-position: 100% 40%; overflow: auto; - box-shadow: 0 0 5px rgba(0,0,0,0.3); + @include box-shadow(0 0 5px rgba(0,0,0,0.3)); & > * { display: none; @@ -309,9 +300,7 @@ h4.static-with-rule { width: 432px; ul#key-tools { - -webkit-box-shadow: 0em 0px 1em 1em $oxfordshire_very_light_green; - -moz-box-shadow: 0em 0px 1em 1em $oxfordshire_very_light_green; - box-shadow: 0em 0px 1em 1em $oxfordshire_very_light_green; + @include box-shadow(0 0 1em 1em $oxfordshire_very_light_green); border-top-width: 2px; } } @@ -345,9 +334,10 @@ input.green-btn{ -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + @include box-shadow( + inset 0 1px 0 rgba(255, 255, 255, 0.2), + 0 1px 2px rgba(0, 0, 0, 0.05) + ); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); font-weight: normal; cursor: pointer; diff --git a/web/cobrands/sass/_base.scss b/web/cobrands/sass/_base.scss index 2c8c90c6f..754e9f75d 100644 --- a/web/cobrands/sass/_base.scss +++ b/web/cobrands/sass/_base.scss @@ -313,24 +313,32 @@ label{ margin: 0 -1em 0.25em; background: #eee; padding: 1em; - > input[type=text], input[type=email] { - margin-bottom:1em; + + & > input[type=text], + & > input[type=email] { + margin-bottom: 1em; + } + + & > label:first-child { + margin-top: 0; } + .title { - font-size:1.25em; - margin:0.5em 0; + font-size: 1.25em; + margin: 0.5em 0; } + h2 { margin: 0 0 0.5em; } + h5 { - margin:0 0 1em; - font: { - size:1.125em; - weight:normal; - } + margin: 0 0 1em; + font-size: 1.125em; + font-weight: normal; + strong { - font-size:2em; + font-size: 2em; margin-#{$right}: 0.25em; } } @@ -342,6 +350,13 @@ label{ margin: 0 0 0.25em; padding: 1em; } + +// When the user is logged in, we show a shorter form-box, +// without a heading before it. So add some space before. +#form-box--logged-in-name { + margin-top: 1.25em; +} + // Prevent grey displaying oddly by giving it a width, and stop odd left margin issue .ie7 .form-box { width: 100%; diff --git a/web/cobrands/sass/_layout.scss b/web/cobrands/sass/_layout.scss index 02dab82d8..bdb8e90a7 100644 --- a/web/cobrands/sass/_layout.scss +++ b/web/cobrands/sass/_layout.scss @@ -222,12 +222,9 @@ h1 { padding: 1em 1em 3em; background: #fff; color: #222; - @include box-shadow(0 0 10px rgba(0,0,0,0.5)); } .iel8 { .content { - // If no box-shadow, just want a boring black border to stand it out from the map. - border: 1px solid #666; //take off margins so we line up properly margin: 0 0.5em; } @@ -392,7 +389,6 @@ body.twothirdswidthpage, body.fullwidthpage { .container { .content { - box-shadow: none; padding: 1em; margin-bottom: 0em; footer { @@ -438,10 +434,6 @@ body.fullwidthpage { .iel8 { body.twothirdswidthpage, body.fullwidthpage { - .content { - border: 0px; - } - .container .content footer a.platform-logo { color: #ffffff; background: none; @@ -470,7 +462,6 @@ body.twothirdswidthpage { z-index: -1; width:13em; padding:1em; - @include box-shadow(0px 0px 6px 1px #000); h2 { margin-top: 0; } @@ -507,7 +498,6 @@ body.authpage { margin-#{$left}: auto; margin-#{$right}: auto; margin-bottom: 0; - box-shadow: none; padding: 1em; // same as .twothirdswidthpage .content } } @@ -532,6 +522,7 @@ body.authpage { //fix table to be a block for ie, float the children .ie6, .ie7 { .tablewrapper { + *zoom: 1; display:block; div {//ie6 doesn't support '>div', so we'll go with the somewhat risker 'div' width:48%; @@ -555,7 +546,6 @@ body.authpage { border-#{$right}: 1em solid transparent; background:none; padding:0; - @include box-shadow(inset rgba(0, 0, 0, 0) 0 0 0); h2 { color:#222; margin-top:0; @@ -719,7 +709,7 @@ body.authpage { ul#key-tools { border-top: 0.25em solid $primary; margin: 0; - @include box-shadow(-0em 0px 1em 1em #fff); + @include box-shadow(0 0 1em 1em #fff); li { border:none; a, input[type=submit] { diff --git a/web/cobrands/sass/_mixins.scss b/web/cobrands/sass/_mixins.scss index 71f9b95a3..5bbbc19eb 100644 --- a/web/cobrands/sass/_mixins.scss +++ b/web/cobrands/sass/_mixins.scss @@ -71,16 +71,16 @@ $right: right; @include experimental(border-radius, $radius, -moz, -webkit, not -o, not -ms, official); } -@mixin box-shadow($shadow) { - @include experimental(box-shadow, $shadow, -moz, -webkit, not -o, not -ms, official); +@mixin box-shadow($shadows...) { + @include experimental(box-shadow, $shadows, -moz, -webkit, not -o, not -ms, official); } @mixin experimental($property, $value, $moz: true, $webkit: true, $o: true, $ms: true, $official: true) { - @if $webkit { -webkit-#{$property} : $value; } - @if $moz { -moz-#{$property} : $value; } - @if $ms { -ms-#{$property} : $value; } - @if $o { -o-#{$property} : $value; } - @if $official { #{$property} : $value; } + @if $webkit { -webkit-#{$property} : #{$value}; } + @if $moz { -moz-#{$property} : #{$value}; } + @if $ms { -ms-#{$property} : #{$value}; } + @if $o { -o-#{$property} : #{$value}; } + @if $official { #{$property} : #{$value}; } } @mixin inline-block($alignment: middle) { diff --git a/web/cobrands/stevenage/layout.scss b/web/cobrands/stevenage/layout.scss index f55ac0d15..901f3fb3e 100644 --- a/web/cobrands/stevenage/layout.scss +++ b/web/cobrands/stevenage/layout.scss @@ -80,7 +80,6 @@ // d523b431 body.fullwidthpage { .content { - @include box-shadow(none); background: none; } } diff --git a/web/cobrands/zurich/layout.scss b/web/cobrands/zurich/layout.scss index 3f24b3685..57cae97e9 100644 --- a/web/cobrands/zurich/layout.scss +++ b/web/cobrands/zurich/layout.scss @@ -4,35 +4,25 @@ // Things to override from parent stylesheet -// White background, so no shadow or margin needed. .content { color: #3c3c3c; - @include box-shadow(none); -} -.iel8 { - .content { - border: none; - } } -// Except on map pages (which includes the front page) -body.mappage .content, body.frontpage .content { + +// Front page content needs a shadow. +// (Purely decorative: No need for border fallback for IE8) +body.frontpage .content { @include box-shadow(0 0 6px 1px #000); } -.iel8 { - body.mappage .content, body.frontpage .content { - border: 1px solid #666; - } -} -/* The header on a map page needs a shadow too */ -body.mappage .nav-wrapper-2 { +// The header on a map page needs a shadow too +body.mappage .nav-wrapper .nav-wrapper-2 { @include box-shadow(0 0 6px 1px #000); } -/* Except on admin pages where there's an admin nav directly underneath it */ +// Except on admin pages where there's an admin nav directly underneath it body.mappage.admin .nav-wrapper-2 { @include box-shadow(none); } -/* Fix positioning of images in the admin */ +// Fix positioning of images in the admin body.admin .admin-nav-wrapper { z-index: 1; } @@ -191,9 +181,6 @@ body.mappage { body.twothirdswidthpage { .content { - aside { - @include box-shadow(none); - } .sticky-sidebar aside { top: 14em; // overrides default value, due to Zurich nav at top of content } diff --git a/web/js/dropzone.js.patch b/web/js/dropzone.js.patch new file mode 100644 index 000000000..030b56a6a --- /dev/null +++ b/web/js/dropzone.js.patch @@ -0,0 +1,36 @@ +--- web/js/src/dropzone.orig.js 2016-06-17 21:29:47.000000000 +0100 ++++ web/js/src/dropzone.js 2016-06-20 11:40:55.000000000 +0100 +@@ -1469,7 +1469,7 @@ + return _results; + }; + +- Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i]; ++ Dropzone.blacklistedBrowsers = [/opera.*(Windows Phone|Macintosh).*version\/12/i]; + + Dropzone.isBrowserSupported = function() { + var capableBrowser, regex, _i, _len, _ref; +@@ -1679,7 +1679,23 @@ + drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) { + var vertSquashRatio; + vertSquashRatio = detectVerticalSquash(img); +- return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); ++ dh = dh / vertSquashRatio; ++ ++ /* An improved version of http://stackoverflow.com/a/28356942/669631 */ ++ var orientation = 0; ++ switch (EXIF.getData(img)) { ++ case 3: orientation = 2; break; ++ case 6: orientation = 1; break; ++ case 8: orientation = -1; break; ++ } ++ if (orientation) { ++ ctx.translate(dx + dw/2, dy + dh/2); ++ ctx.rotate(orientation * Math.PI / 2); ++ dx = -dw/2; ++ dy = -dh/2; ++ } ++ ++ return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh); + }; + + diff --git a/web/js/dropzone.min.js b/web/js/dropzone.min.js index f460b6c50..ff19898e9 100755..100644 --- a/web/js/dropzone.min.js +++ b/web/js/dropzone.min.js @@ -1,2 +1,60 @@ -(function(){var a,b,c,d,e,f,g,h,i=[].slice,j={}.hasOwnProperty,k=function(a,b){function c(){this.constructor=a}for(var d in b)j.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a};g=function(){},b=function(){function a(){}return a.prototype.addEventListener=a.prototype.on,a.prototype.on=function(a,b){return this._callbacks=this._callbacks||{},this._callbacks[a]||(this._callbacks[a]=[]),this._callbacks[a].push(b),this},a.prototype.emit=function(){var a,b,c,d,e,f;if(d=arguments[0],a=2<=arguments.length?i.call(arguments,1):[],this._callbacks=this._callbacks||{},c=this._callbacks[d])for(e=0,f=c.length;f>e;e++)b=c[e],b.apply(this,a);return this},a.prototype.removeListener=a.prototype.off,a.prototype.removeAllListeners=a.prototype.off,a.prototype.removeEventListener=a.prototype.off,a.prototype.off=function(a,b){var c,d,e,f,g;if(!this._callbacks||0===arguments.length)return this._callbacks={},this;if(d=this._callbacks[a],!d)return this;if(1===arguments.length)return delete this._callbacks[a],this;for(e=f=0,g=d.length;g>f;e=++f)if(c=d[e],c===b){d.splice(e,1);break}return this},a}(),a=function(a){function c(a,b){var e,f,g;if(this.element=a,this.version=c.version,this.defaultOptions.previewTemplate=this.defaultOptions.previewTemplate.replace(/\n*/g,""),this.clickableElements=[],this.listeners=[],this.files=[],"string"==typeof this.element&&(this.element=document.querySelector(this.element)),!this.element||null==this.element.nodeType)throw new Error("Invalid dropzone element.");if(this.element.dropzone)throw new Error("Dropzone already attached.");if(c.instances.push(this),this.element.dropzone=this,e=null!=(g=c.optionsForElement(this.element))?g:{},this.options=d({},this.defaultOptions,e,null!=b?b:{}),this.options.forceFallback||!c.isBrowserSupported())return this.options.fallback.call(this);if(null==this.options.url&&(this.options.url=this.element.getAttribute("action")),!this.options.url)throw new Error("No URL provided.");if(this.options.acceptedFiles&&this.options.acceptedMimeTypes)throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");this.options.acceptedMimeTypes&&(this.options.acceptedFiles=this.options.acceptedMimeTypes,delete this.options.acceptedMimeTypes),this.options.method=this.options.method.toUpperCase(),(f=this.getExistingFallback())&&f.parentNode&&f.parentNode.removeChild(f),this.options.previewsContainer!==!1&&(this.previewsContainer=this.options.previewsContainer?c.getElement(this.options.previewsContainer,"previewsContainer"):this.element),this.options.clickable&&(this.clickableElements=this.options.clickable===!0?[this.element]:c.getElements(this.options.clickable,"clickable")),this.init()}var d,e;return k(c,a),c.prototype.Emitter=b,c.prototype.events=["drop","dragstart","dragend","dragenter","dragover","dragleave","addedfile","addedfiles","removedfile","thumbnail","error","errormultiple","processing","processingmultiple","uploadprogress","totaluploadprogress","sending","sendingmultiple","success","successmultiple","canceled","canceledmultiple","complete","completemultiple","reset","maxfilesexceeded","maxfilesreached","queuecomplete"],c.prototype.defaultOptions={url:null,method:"post",withCredentials:!1,parallelUploads:2,uploadMultiple:!1,maxFilesize:256,paramName:"file",createImageThumbnails:!0,maxThumbnailFilesize:10,thumbnailWidth:120,thumbnailHeight:120,filesizeBase:1e3,maxFiles:null,params:{},clickable:!0,ignoreHiddenFiles:!0,acceptedFiles:null,acceptedMimeTypes:null,autoProcessQueue:!0,autoQueue:!0,addRemoveLinks:!1,previewsContainer:null,hiddenInputContainer:"body",capture:null,dictDefaultMessage:"Drop files here to upload",dictFallbackMessage:"Your browser does not support drag'n'drop file uploads.",dictFallbackText:"Please use the fallback form below to upload your files like in the olden days.",dictFileTooBig:"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",dictInvalidFileType:"You can't upload files of this type.",dictResponseError:"Server responded with {{statusCode}} code.",dictCancelUpload:"Cancel upload",dictCancelUploadConfirmation:"Are you sure you want to cancel this upload?",dictRemoveFile:"Remove file",dictRemoveFileConfirmation:null,dictMaxFilesExceeded:"You can not upload any more files.",accept:function(a,b){return b()},init:function(){return g},forceFallback:!1,fallback:function(){var a,b,d,e,f,g;for(this.element.className=""+this.element.className+" dz-browser-not-supported",g=this.element.getElementsByTagName("div"),e=0,f=g.length;f>e;e++)a=g[e],/(^| )dz-message($| )/.test(a.className)&&(b=a,a.className="dz-message");return b||(b=c.createElement('<div class="dz-message"><span></span></div>'),this.element.appendChild(b)),d=b.getElementsByTagName("span")[0],d&&(null!=d.textContent?d.textContent=this.options.dictFallbackMessage:null!=d.innerText&&(d.innerText=this.options.dictFallbackMessage)),this.element.appendChild(this.getFallbackForm())},resize:function(a){var b,c,d;return b={srcX:0,srcY:0,srcWidth:a.width,srcHeight:a.height},c=a.width/a.height,b.optWidth=this.options.thumbnailWidth,b.optHeight=this.options.thumbnailHeight,null==b.optWidth&&null==b.optHeight?(b.optWidth=b.srcWidth,b.optHeight=b.srcHeight):null==b.optWidth?b.optWidth=c*b.optHeight:null==b.optHeight&&(b.optHeight=1/c*b.optWidth),d=b.optWidth/b.optHeight,a.height<b.optHeight||a.width<b.optWidth?(b.trgHeight=b.srcHeight,b.trgWidth=b.srcWidth):c>d?(b.srcHeight=a.height,b.srcWidth=b.srcHeight*d):(b.srcWidth=a.width,b.srcHeight=b.srcWidth/d),b.srcX=(a.width-b.srcWidth)/2,b.srcY=(a.height-b.srcHeight)/2,b},drop:function(){return this.element.classList.remove("dz-drag-hover")},dragstart:g,dragend:function(){return this.element.classList.remove("dz-drag-hover")},dragenter:function(){return this.element.classList.add("dz-drag-hover")},dragover:function(){return this.element.classList.add("dz-drag-hover")},dragleave:function(){return this.element.classList.remove("dz-drag-hover")},paste:g,reset:function(){return this.element.classList.remove("dz-started")},addedfile:function(a){var b,d,e,f,g,h,i,j,k,l,m,n,o;if(this.element===this.previewsContainer&&this.element.classList.add("dz-started"),this.previewsContainer){for(a.previewElement=c.createElement(this.options.previewTemplate.trim()),a.previewTemplate=a.previewElement,this.previewsContainer.appendChild(a.previewElement),l=a.previewElement.querySelectorAll("[data-dz-name]"),f=0,i=l.length;i>f;f++)b=l[f],b.textContent=a.name;for(m=a.previewElement.querySelectorAll("[data-dz-size]"),g=0,j=m.length;j>g;g++)b=m[g],b.innerHTML=this.filesize(a.size);for(this.options.addRemoveLinks&&(a._removeLink=c.createElement('<a class="dz-remove" href="javascript:undefined;" data-dz-remove>'+this.options.dictRemoveFile+"</a>"),a.previewElement.appendChild(a._removeLink)),d=function(b){return function(d){return d.preventDefault(),d.stopPropagation(),a.status===c.UPLOADING?c.confirm(b.options.dictCancelUploadConfirmation,function(){return b.removeFile(a)}):b.options.dictRemoveFileConfirmation?c.confirm(b.options.dictRemoveFileConfirmation,function(){return b.removeFile(a)}):b.removeFile(a)}}(this),n=a.previewElement.querySelectorAll("[data-dz-remove]"),o=[],h=0,k=n.length;k>h;h++)e=n[h],o.push(e.addEventListener("click",d));return o}},removedfile:function(a){var b;return a.previewElement&&null!=(b=a.previewElement)&&b.parentNode.removeChild(a.previewElement),this._updateMaxFilesReachedClass()},thumbnail:function(a,b){var c,d,e,f;if(a.previewElement){for(a.previewElement.classList.remove("dz-file-preview"),f=a.previewElement.querySelectorAll("[data-dz-thumbnail]"),d=0,e=f.length;e>d;d++)c=f[d],c.alt=a.name,c.src=b;return setTimeout(function(){return function(){return a.previewElement.classList.add("dz-image-preview")}}(this),1)}},error:function(a,b){var c,d,e,f,g;if(a.previewElement){for(a.previewElement.classList.add("dz-error"),"String"!=typeof b&&b.error&&(b=b.error),f=a.previewElement.querySelectorAll("[data-dz-errormessage]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.textContent=b);return g}},errormultiple:g,processing:function(a){return a.previewElement&&(a.previewElement.classList.add("dz-processing"),a._removeLink)?a._removeLink.textContent=this.options.dictCancelUpload:void 0},processingmultiple:g,uploadprogress:function(a,b){var c,d,e,f,g;if(a.previewElement){for(f=a.previewElement.querySelectorAll("[data-dz-uploadprogress]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push("PROGRESS"===c.nodeName?c.value=b:c.style.width=""+b+"%");return g}},totaluploadprogress:g,sending:g,sendingmultiple:g,success:function(a){return a.previewElement?a.previewElement.classList.add("dz-success"):void 0},successmultiple:g,canceled:function(a){return this.emit("error",a,"Upload canceled.")},canceledmultiple:g,complete:function(a){return a._removeLink&&(a._removeLink.textContent=this.options.dictRemoveFile),a.previewElement?a.previewElement.classList.add("dz-complete"):void 0},completemultiple:g,maxfilesexceeded:g,maxfilesreached:g,queuecomplete:g,addedfiles:g,previewTemplate:'<div class="dz-preview dz-file-preview">\n <div class="dz-image"><img data-dz-thumbnail /></div>\n <div class="dz-details">\n <div class="dz-size"><span data-dz-size></span></div>\n <div class="dz-filename"><span data-dz-name></span></div>\n </div>\n <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>\n <div class="dz-error-message"><span data-dz-errormessage></span></div>\n <div class="dz-success-mark">\n <svg width="54px" height="54px" viewBox="0 0 54 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">\n <title>Check</title>\n <defs></defs>\n <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">\n <path d="M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z" id="Oval-2" stroke-opacity="0.198794158" stroke="#747474" fill-opacity="0.816519475" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>\n </g>\n </svg>\n </div>\n <div class="dz-error-mark">\n <svg width="54px" height="54px" viewBox="0 0 54 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">\n <title>Error</title>\n <defs></defs>\n <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">\n <g id="Check-+-Oval-2" sketch:type="MSLayerGroup" stroke="#747474" stroke-opacity="0.198794158" fill="#FFFFFF" fill-opacity="0.816519475">\n <path d="M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z" id="Oval-2" sketch:type="MSShapeGroup"></path>\n </g>\n </g>\n </svg>\n </div>\n</div>'},d=function(){var a,b,c,d,e,f,g;for(d=arguments[0],c=2<=arguments.length?i.call(arguments,1):[],f=0,g=c.length;g>f;f++){b=c[f];for(a in b)e=b[a],d[a]=e}return d},c.prototype.getAcceptedFiles=function(){var a,b,c,d,e;for(d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.accepted&&e.push(a);return e},c.prototype.getRejectedFiles=function(){var a,b,c,d,e;for(d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.accepted||e.push(a);return e},c.prototype.getFilesWithStatus=function(a){var b,c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)b=e[c],b.status===a&&f.push(b);return f},c.prototype.getQueuedFiles=function(){return this.getFilesWithStatus(c.QUEUED)},c.prototype.getUploadingFiles=function(){return this.getFilesWithStatus(c.UPLOADING)},c.prototype.getAddedFiles=function(){return this.getFilesWithStatus(c.ADDED)},c.prototype.getActiveFiles=function(){var a,b,d,e,f;for(e=this.files,f=[],b=0,d=e.length;d>b;b++)a=e[b],(a.status===c.UPLOADING||a.status===c.QUEUED)&&f.push(a);return f},c.prototype.init=function(){var a,b,d,e,f,g,h;for("form"===this.element.tagName&&this.element.setAttribute("enctype","multipart/form-data"),this.element.classList.contains("dropzone")&&!this.element.querySelector(".dz-message")&&this.element.appendChild(c.createElement('<div class="dz-default dz-message"><span>'+this.options.dictDefaultMessage+"</span></div>")),this.clickableElements.length&&(d=function(a){return function(){return a.hiddenFileInput&&a.hiddenFileInput.parentNode.removeChild(a.hiddenFileInput),a.hiddenFileInput=document.createElement("input"),a.hiddenFileInput.setAttribute("type","file"),(null==a.options.maxFiles||a.options.maxFiles>1)&&a.hiddenFileInput.setAttribute("multiple","multiple"),a.hiddenFileInput.className="dz-hidden-input",null!=a.options.acceptedFiles&&a.hiddenFileInput.setAttribute("accept",a.options.acceptedFiles),null!=a.options.capture&&a.hiddenFileInput.setAttribute("capture",a.options.capture),a.hiddenFileInput.style.visibility="hidden",a.hiddenFileInput.style.position="absolute",a.hiddenFileInput.style.top="0",a.hiddenFileInput.style.left="0",a.hiddenFileInput.style.height="0",a.hiddenFileInput.style.width="0",document.querySelector(a.options.hiddenInputContainer).appendChild(a.hiddenFileInput),a.hiddenFileInput.addEventListener("change",function(){var b,c,e,f;if(c=a.hiddenFileInput.files,c.length)for(e=0,f=c.length;f>e;e++)b=c[e],a.addFile(b);return a.emit("addedfiles",c),d()})}}(this))(),this.URL=null!=(g=window.URL)?g:window.webkitURL,h=this.events,e=0,f=h.length;f>e;e++)a=h[e],this.on(a,this.options[a]);return this.on("uploadprogress",function(a){return function(){return a.updateTotalUploadProgress()}}(this)),this.on("removedfile",function(a){return function(){return a.updateTotalUploadProgress()}}(this)),this.on("canceled",function(a){return function(b){return a.emit("complete",b)}}(this)),this.on("complete",function(a){return function(){return 0===a.getAddedFiles().length&&0===a.getUploadingFiles().length&&0===a.getQueuedFiles().length?setTimeout(function(){return a.emit("queuecomplete")},0):void 0}}(this)),b=function(a){return a.stopPropagation(),a.preventDefault?a.preventDefault():a.returnValue=!1},this.listeners=[{element:this.element,events:{dragstart:function(a){return function(b){return a.emit("dragstart",b)}}(this),dragenter:function(a){return function(c){return b(c),a.emit("dragenter",c)}}(this),dragover:function(a){return function(c){var d;try{d=c.dataTransfer.effectAllowed}catch(e){}return c.dataTransfer.dropEffect="move"===d||"linkMove"===d?"move":"copy",b(c),a.emit("dragover",c)}}(this),dragleave:function(a){return function(b){return a.emit("dragleave",b)}}(this),drop:function(a){return function(c){return b(c),a.drop(c)}}(this),dragend:function(a){return function(b){return a.emit("dragend",b)}}(this)}}],this.clickableElements.forEach(function(a){return function(b){return a.listeners.push({element:b,events:{click:function(d){return(b!==a.element||d.target===a.element||c.elementInside(d.target,a.element.querySelector(".dz-message")))&&a.hiddenFileInput.click(),!0}}})}}(this)),this.enable(),this.options.init.call(this)},c.prototype.destroy=function(){var a;return this.disable(),this.removeAllFiles(!0),(null!=(a=this.hiddenFileInput)?a.parentNode:void 0)&&(this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput),this.hiddenFileInput=null),delete this.element.dropzone,c.instances.splice(c.instances.indexOf(this),1)},c.prototype.updateTotalUploadProgress=function(){var a,b,c,d,e,f,g,h;if(d=0,c=0,a=this.getActiveFiles(),a.length){for(h=this.getActiveFiles(),f=0,g=h.length;g>f;f++)b=h[f],d+=b.upload.bytesSent,c+=b.upload.total;e=100*d/c}else e=100;return this.emit("totaluploadprogress",e,c,d)},c.prototype._getParamName=function(a){return"function"==typeof this.options.paramName?this.options.paramName(a):""+this.options.paramName+(this.options.uploadMultiple?"["+a+"]":"")},c.prototype.getFallbackForm=function(){var a,b,d,e;return(a=this.getExistingFallback())?a:(d='<div class="dz-fallback">',this.options.dictFallbackText&&(d+="<p>"+this.options.dictFallbackText+"</p>"),d+='<input type="file" name="'+this._getParamName(0)+'" '+(this.options.uploadMultiple?'multiple="multiple"':void 0)+' /><input type="submit" value="Upload!"></div>',b=c.createElement(d),"FORM"!==this.element.tagName?(e=c.createElement('<form action="'+this.options.url+'" enctype="multipart/form-data" method="'+this.options.method+'"></form>'),e.appendChild(b)):(this.element.setAttribute("enctype","multipart/form-data"),this.element.setAttribute("method",this.options.method)),null!=e?e:b)},c.prototype.getExistingFallback=function(){var a,b,c,d,e,f;for(b=function(a){var b,c,d;for(c=0,d=a.length;d>c;c++)if(b=a[c],/(^| )fallback($| )/.test(b.className))return b},f=["div","form"],d=0,e=f.length;e>d;d++)if(c=f[d],a=b(this.element.getElementsByTagName(c)))return a},c.prototype.setupEventListeners=function(){var a,b,c,d,e,f,g;for(f=this.listeners,g=[],d=0,e=f.length;e>d;d++)a=f[d],g.push(function(){var d,e;d=a.events,e=[];for(b in d)c=d[b],e.push(a.element.addEventListener(b,c,!1));return e}());return g},c.prototype.removeEventListeners=function(){var a,b,c,d,e,f,g;for(f=this.listeners,g=[],d=0,e=f.length;e>d;d++)a=f[d],g.push(function(){var d,e;d=a.events,e=[];for(b in d)c=d[b],e.push(a.element.removeEventListener(b,c,!1));return e}());return g},c.prototype.disable=function(){var a,b,c,d,e;for(this.clickableElements.forEach(function(a){return a.classList.remove("dz-clickable")}),this.removeEventListeners(),d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(this.cancelUpload(a));return e},c.prototype.enable=function(){return this.clickableElements.forEach(function(a){return a.classList.add("dz-clickable")}),this.setupEventListeners()},c.prototype.filesize=function(a){var b,c,d,e,f,g,h,i;if(d=0,e="b",a>0){for(g=["TB","GB","MB","KB","b"],c=h=0,i=g.length;i>h;c=++h)if(f=g[c],b=Math.pow(this.options.filesizeBase,4-c)/10,a>=b){d=a/Math.pow(this.options.filesizeBase,4-c),e=f;break}d=Math.round(10*d)/10}return"<strong>"+d+"</strong> "+e},c.prototype._updateMaxFilesReachedClass=function(){return null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit("maxfilesreached",this.files),this.element.classList.add("dz-max-files-reached")):this.element.classList.remove("dz-max-files-reached")},c.prototype.drop=function(a){var b,c;a.dataTransfer&&(this.emit("drop",a),b=a.dataTransfer.files,this.emit("addedfiles",b),b.length&&(c=a.dataTransfer.items,c&&c.length&&null!=c[0].webkitGetAsEntry?this._addFilesFromItems(c):this.handleFiles(b)))},c.prototype.paste=function(a){var b,c;if(null!=(null!=a&&null!=(c=a.clipboardData)?c.items:void 0))return this.emit("paste",a),b=a.clipboardData.items,b.length?this._addFilesFromItems(b):void 0},c.prototype.handleFiles=function(a){var b,c,d,e;for(e=[],c=0,d=a.length;d>c;c++)b=a[c],e.push(this.addFile(b));return e},c.prototype._addFilesFromItems=function(a){var b,c,d,e,f;for(f=[],d=0,e=a.length;e>d;d++)c=a[d],f.push(null!=c.webkitGetAsEntry&&(b=c.webkitGetAsEntry())?b.isFile?this.addFile(c.getAsFile()):b.isDirectory?this._addFilesFromDirectory(b,b.name):void 0:null!=c.getAsFile?null==c.kind||"file"===c.kind?this.addFile(c.getAsFile()):void 0:void 0);return f},c.prototype._addFilesFromDirectory=function(a,b){var c,d;return c=a.createReader(),d=function(a){return function(c){var d,e,f;for(e=0,f=c.length;f>e;e++)d=c[e],d.isFile?d.file(function(c){return a.options.ignoreHiddenFiles&&"."===c.name.substring(0,1)?void 0:(c.fullPath=""+b+"/"+c.name,a.addFile(c))}):d.isDirectory&&a._addFilesFromDirectory(d,""+b+"/"+d.name)}}(this),c.readEntries(d,function(a){return"undefined"!=typeof console&&null!==console&&"function"==typeof console.log?console.log(a):void 0})},c.prototype.accept=function(a,b){return a.size>1024*this.options.maxFilesize*1024?b(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(a.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize)):c.isValidFile(a,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(b(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles)),this.emit("maxfilesexceeded",a)):this.options.accept.call(this,a,b):b(this.options.dictInvalidFileType)},c.prototype.addFile=function(a){return a.upload={progress:0,total:a.size,bytesSent:0},this.files.push(a),a.status=c.ADDED,this.emit("addedfile",a),this._enqueueThumbnail(a),this.accept(a,function(b){return function(c){return c?(a.accepted=!1,b._errorProcessing([a],c)):(a.accepted=!0,b.options.autoQueue&&b.enqueueFile(a)),b._updateMaxFilesReachedClass()}}(this))},c.prototype.enqueueFiles=function(a){var b,c,d;for(c=0,d=a.length;d>c;c++)b=a[c],this.enqueueFile(b);return null},c.prototype.enqueueFile=function(a){if(a.status!==c.ADDED||a.accepted!==!0)throw new Error("This file can't be queued because it has already been processed or was rejected.");return a.status=c.QUEUED,this.options.autoProcessQueue?setTimeout(function(a){return function(){return a.processQueue()}}(this),0):void 0},c.prototype._thumbnailQueue=[],c.prototype._processingThumbnail=!1,c.prototype._enqueueThumbnail=function(a){return this.options.createImageThumbnails&&a.type.match(/image.*/)&&a.size<=1024*this.options.maxThumbnailFilesize*1024?(this._thumbnailQueue.push(a),setTimeout(function(a){return function(){return a._processThumbnailQueue()}}(this),0)):void 0},c.prototype._processThumbnailQueue=function(){return this._processingThumbnail||0===this._thumbnailQueue.length?void 0:(this._processingThumbnail=!0,this.createThumbnail(this._thumbnailQueue.shift(),function(a){return function(){return a._processingThumbnail=!1,a._processThumbnailQueue()}}(this)))},c.prototype.removeFile=function(a){return a.status===c.UPLOADING&&this.cancelUpload(a),this.files=h(this.files,a),this.emit("removedfile",a),0===this.files.length?this.emit("reset"):void 0},c.prototype.removeAllFiles=function(a){var b,d,e,f;for(null==a&&(a=!1),f=this.files.slice(),d=0,e=f.length;e>d;d++)b=f[d],(b.status!==c.UPLOADING||a)&&this.removeFile(b);return null},c.prototype.createThumbnail=function(a,b){var c;return c=new FileReader,c.onload=function(d){return function(){return"image/svg+xml"===a.type?(d.emit("thumbnail",a,c.result),void(null!=b&&b())):d.createThumbnailFromUrl(a,c.result,b)}}(this),c.readAsDataURL(a)},c.prototype.createThumbnailFromUrl=function(a,b,c,d){var e;return e=document.createElement("img"),d&&(e.crossOrigin=d),e.onload=function(b){return function(){var d,g,h,i,j,k,l,m;return a.width=e.width,a.height=e.height,h=b.options.resize.call(b,a),null==h.trgWidth&&(h.trgWidth=h.optWidth),null==h.trgHeight&&(h.trgHeight=h.optHeight),d=document.createElement("canvas"),g=d.getContext("2d"),d.width=h.trgWidth,d.height=h.trgHeight,f(g,e,null!=(j=h.srcX)?j:0,null!=(k=h.srcY)?k:0,h.srcWidth,h.srcHeight,null!=(l=h.trgX)?l:0,null!=(m=h.trgY)?m:0,h.trgWidth,h.trgHeight),i=d.toDataURL("image/png"),b.emit("thumbnail",a,i),null!=c?c():void 0}}(this),null!=c&&(e.onerror=c),e.src=b},c.prototype.processQueue=function(){var a,b,c,d;if(b=this.options.parallelUploads,c=this.getUploadingFiles().length,a=c,!(c>=b)&&(d=this.getQueuedFiles(),d.length>0)){if(this.options.uploadMultiple)return this.processFiles(d.slice(0,b-c));for(;b>a;){if(!d.length)return;this.processFile(d.shift()),a++}}},c.prototype.processFile=function(a){return this.processFiles([a])},c.prototype.processFiles=function(a){var b,d,e;for(d=0,e=a.length;e>d;d++)b=a[d],b.processing=!0,b.status=c.UPLOADING,this.emit("processing",b);return this.options.uploadMultiple&&this.emit("processingmultiple",a),this.uploadFiles(a)},c.prototype._getFilesWithXhr=function(a){var b,c;return c=function(){var c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)b=e[c],b.xhr===a&&f.push(b);return f}.call(this)},c.prototype.cancelUpload=function(a){var b,d,e,f,g,h,i;if(a.status===c.UPLOADING){for(d=this._getFilesWithXhr(a.xhr),e=0,g=d.length;g>e;e++)b=d[e],b.status=c.CANCELED;for(a.xhr.abort(),f=0,h=d.length;h>f;f++)b=d[f],this.emit("canceled",b);this.options.uploadMultiple&&this.emit("canceledmultiple",d)}else((i=a.status)===c.ADDED||i===c.QUEUED)&&(a.status=c.CANCELED,this.emit("canceled",a),this.options.uploadMultiple&&this.emit("canceledmultiple",[a]));return this.options.autoProcessQueue?this.processQueue():void 0},e=function(){var a,b;return b=arguments[0],a=2<=arguments.length?i.call(arguments,1):[],"function"==typeof b?b.apply(this,a):b},c.prototype.uploadFile=function(a){return this.uploadFiles([a])},c.prototype.uploadFiles=function(a){var b,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L;for(w=new XMLHttpRequest,x=0,B=a.length;B>x;x++)b=a[x],b.xhr=w;p=e(this.options.method,a),u=e(this.options.url,a),w.open(p,u,!0),w.withCredentials=!!this.options.withCredentials,s=null,g=function(c){return function(){var d,e,f;for(f=[],d=0,e=a.length;e>d;d++)b=a[d],f.push(c._errorProcessing(a,s||c.options.dictResponseError.replace("{{statusCode}}",w.status),w));return f}}(this),t=function(c){return function(d){var e,f,g,h,i,j,k,l,m;if(null!=d)for(f=100*d.loaded/d.total,g=0,j=a.length;j>g;g++)b=a[g],b.upload={progress:f,total:d.total,bytesSent:d.loaded};else{for(e=!0,f=100,h=0,k=a.length;k>h;h++)b=a[h],(100!==b.upload.progress||b.upload.bytesSent!==b.upload.total)&&(e=!1),b.upload.progress=f,b.upload.bytesSent=b.upload.total;if(e)return}for(m=[],i=0,l=a.length;l>i;i++)b=a[i],m.push(c.emit("uploadprogress",b,f,b.upload.bytesSent));return m}}(this),w.onload=function(b){return function(d){var e;if(a[0].status!==c.CANCELED&&4===w.readyState){if(s=w.responseText,w.getResponseHeader("content-type")&&~w.getResponseHeader("content-type").indexOf("application/json"))try{s=JSON.parse(s)}catch(f){d=f,s="Invalid JSON response from server."}return t(),200<=(e=w.status)&&300>e?b._finished(a,s,d):g()}}}(this),w.onerror=function(){return function(){return a[0].status!==c.CANCELED?g():void 0}}(this),r=null!=(G=w.upload)?G:w,r.onprogress=t,j={Accept:"application/json","Cache-Control":"no-cache","X-Requested-With":"XMLHttpRequest"},this.options.headers&&d(j,this.options.headers);for(h in j)i=j[h],i&&w.setRequestHeader(h,i);if(f=new FormData,this.options.params){H=this.options.params;for(o in H)v=H[o],f.append(o,v)}for(y=0,C=a.length;C>y;y++)b=a[y],this.emit("sending",b,w,f);if(this.options.uploadMultiple&&this.emit("sendingmultiple",a,w,f),"FORM"===this.element.tagName)for(I=this.element.querySelectorAll("input, textarea, select, button"),z=0,D=I.length;D>z;z++)if(l=I[z],m=l.getAttribute("name"),n=l.getAttribute("type"),"SELECT"===l.tagName&&l.hasAttribute("multiple"))for(J=l.options,A=0,E=J.length;E>A;A++)q=J[A],q.selected&&f.append(m,q.value);else(!n||"checkbox"!==(K=n.toLowerCase())&&"radio"!==K||l.checked)&&f.append(m,l.value);for(k=F=0,L=a.length-1;L>=0?L>=F:F>=L;k=L>=0?++F:--F)f.append(this._getParamName(k),a[k],a[k].name);return this.submitRequest(w,f,a)},c.prototype.submitRequest=function(a,b){return a.send(b)},c.prototype._finished=function(a,b,d){var e,f,g;for(f=0,g=a.length;g>f;f++)e=a[f],e.status=c.SUCCESS,this.emit("success",e,b,d),this.emit("complete",e);return this.options.uploadMultiple&&(this.emit("successmultiple",a,b,d),this.emit("completemultiple",a)),this.options.autoProcessQueue?this.processQueue():void 0},c.prototype._errorProcessing=function(a,b,d){var e,f,g;for(f=0,g=a.length;g>f;f++)e=a[f],e.status=c.ERROR,this.emit("error",e,b,d),this.emit("complete",e);return this.options.uploadMultiple&&(this.emit("errormultiple",a,b,d),this.emit("completemultiple",a)),this.options.autoProcessQueue?this.processQueue():void 0},c}(b),a.version="4.2.0",a.options={},a.optionsForElement=function(b){return b.getAttribute("id")?a.options[c(b.getAttribute("id"))]:void 0},a.instances=[],a.forElement=function(a){if("string"==typeof a&&(a=document.querySelector(a)),null==(null!=a?a.dropzone:void 0))throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");return a.dropzone},a.autoDiscover=!0,a.discover=function(){var b,c,d,e,f,g;for(document.querySelectorAll?d=document.querySelectorAll(".dropzone"):(d=[],b=function(a){var b,c,e,f;for(f=[],c=0,e=a.length;e>c;c++)b=a[c],f.push(/(^| )dropzone($| )/.test(b.className)?d.push(b):void 0);return f},b(document.getElementsByTagName("div")),b(document.getElementsByTagName("form"))),g=[],e=0,f=d.length;f>e;e++)c=d[e],g.push(a.optionsForElement(c)!==!1?new a(c):void 0);return g},a.blacklistedBrowsers=[/opera.*(Windows Phone|Macintosh).*version\/12/i],a.isBrowserSupported=function(){var b,c,d,e,f;if(b=!0,window.File&&window.FileReader&&window.FileList&&window.Blob&&window.FormData&&document.querySelector)if("classList"in document.createElement("a"))for(f=a.blacklistedBrowsers,d=0,e=f.length;e>d;d++)c=f[d],c.test(navigator.userAgent)&&(b=!1);else b=!1;else b=!1;return b},h=function(a,b){var c,d,e,f;for(f=[],d=0,e=a.length;e>d;d++)c=a[d],c!==b&&f.push(c);return f},c=function(a){return a.replace(/[\-_](\w)/g,function(a){return a.charAt(1).toUpperCase()})},a.createElement=function(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.childNodes[0]},a.elementInside=function(a,b){if(a===b)return!0;for(;a=a.parentNode;)if(a===b)return!0;return!1},a.getElement=function(a,b){var c;if("string"==typeof a?c=document.querySelector(a):null!=a.nodeType&&(c=a),null==c)throw new Error("Invalid `"+b+"` option provided. Please provide a CSS selector or a plain HTML element.");return c},a.getElements=function(a,b){var c,d,e,f,g,h,i,j;if(a instanceof Array){e=[];try{for(f=0,h=a.length;h>f;f++)d=a[f],e.push(this.getElement(d,b))}catch(k){c=k,e=null}}else if("string"==typeof a)for(e=[],j=document.querySelectorAll(a),g=0,i=j.length;i>g;g++)d=j[g],e.push(d);else null!=a.nodeType&&(e=[a]);if(null==e||!e.length)throw new Error("Invalid `"+b+"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");return e},a.confirm=function(a,b,c){return window.confirm(a)?b():null!=c?c():void 0},a.isValidFile=function(a,b){var c,d,e,f,g;if(!b)return!0;for(b=b.split(","),d=a.type,c=d.replace(/\/.*$/,""),f=0,g=b.length;g>f;f++)if(e=b[f],e=e.trim(),"."===e.charAt(0)){if(-1!==a.name.toLowerCase().indexOf(e.toLowerCase(),a.name.length-e.length))return!0}else if(/\/\*$/.test(e)){if(c===e.replace(/\/.*$/,""))return!0}else if(d===e)return!0;return!1},"undefined"!=typeof jQuery&&null!==jQuery&&(jQuery.fn.dropzone=function(b){return this.each(function(){return new a(this,b)})}),"undefined"!=typeof module&&null!==module?module.exports=a:window.Dropzone=a,a.ADDED="added",a.QUEUED="queued",a.ACCEPTED=a.QUEUED,a.UPLOADING="uploading",a.PROCESSING=a.UPLOADING,a.CANCELED="canceled",a.ERROR="error",a.SUCCESS="success",e=function(a){var b,c,d,e,f,g,h,i,j,k; -for(h=a.naturalWidth,g=a.naturalHeight,c=document.createElement("canvas"),c.width=1,c.height=g,d=c.getContext("2d"),d.drawImage(a,0,0),e=d.getImageData(0,0,1,g).data,k=0,f=g,i=g;i>k;)b=e[4*(i-1)+3],0===b?f=i:k=i,i=f+k>>1;return j=i/g,0===j?1:j},f=function(a,b,c,d,f,g,h,i,j,k){var l;return l=e(b),a.drawImage(b,c,d,f,g,h,i,j,k/l)},d=function(a,b){var c,d,e,f,g,h,i,j,k;if(e=!1,k=!0,d=a.document,j=d.documentElement,c=d.addEventListener?"addEventListener":"attachEvent",i=d.addEventListener?"removeEventListener":"detachEvent",h=d.addEventListener?"":"on",f=function(c){return"readystatechange"!==c.type||"complete"===d.readyState?(("load"===c.type?a:d)[i](h+c.type,f,!1),!e&&(e=!0)?b.call(a,c.type||c):void 0):void 0},g=function(){var a;try{j.doScroll("left")}catch(b){return a=b,void setTimeout(g,50)}return f("poll")},"complete"!==d.readyState){if(d.createEventObject&&j.doScroll){try{k=!a.frameElement}catch(l){}k&&g()}return d[c](h+"DOMContentLoaded",f,!1),d[c](h+"readystatechange",f,!1),a[c](h+"load",f,!1)}},a._autoDiscoverFunction=function(){return a.autoDiscover?a.discover():void 0},d(window,a._autoDiscoverFunction)}).call(this); +(function(){function k(k,n){for(var p="",l=n;l<n+4;l++)p+=String.fromCharCode(k.getUint8(l));if("Exif"!=p)return!1;l=n+6;if(18761==k.getUint16(l))p=!1;else if(19789==k.getUint16(l))p=!0;else return!1;if(42!=k.getUint16(l+2,!p))return!1;var r=k.getUint32(l+4,!p);if(8>r)return!1;var l=l+r,r=k.getUint16(l,!p),v,w;for(w=0;w<r;w++)if(v=l+12*w+2,274==k.getUint16(v,!p))return parseInt(k.getUint16(v+8,!p),10);return!1}var w={};window.EXIF=w;w.getData=function(q){if((q instanceof Image||q instanceof HTMLImageElement)&& +!q.complete)return!1;q=q.src.replace(/^data\:([^\;]+)\;base64,/gmi,"");var n=atob(q),p=n.length;q=new ArrayBuffer(p);for(var l=new Uint8Array(q),r=0;r<p;r++)l[r]=n.charCodeAt(r);n=new DataView(q);if(255!=n.getUint8(0)||216!=n.getUint8(1))return!1;p=2;for(q=q.byteLength;p<q;){if(255!=n.getUint8(p))return!1;l=n.getUint8(p+1);if(225==l)return k(n,p+4);p+=2+n.getUint16(p+2)}}})();(function(){var k,w,q,n,p,l,r,v=[].slice,A={}.hasOwnProperty,B=function(e,c){function u(){this.constructor=e}for(var h in c)A.call(c,h)&&(e[h]=c[h]);u.prototype=c.prototype;e.prototype=new u;e.__super__=c.prototype;return e};l=function(){};w=function(){function e(){}e.prototype.addEventListener=e.prototype.on;e.prototype.on=function(c,e){this._callbacks=this._callbacks||{};this._callbacks[c]||(this._callbacks[c]=[]);this._callbacks[c].push(e);return this};e.prototype.emit=function(){var c,e,h,a,b; +e=arguments[0];c=2<=arguments.length?v.call(arguments,1):[];this._callbacks=this._callbacks||{};if(h=this._callbacks[e])for(a=0,b=h.length;a<b;a++)e=h[a],e.apply(this,c);return this};e.prototype.removeListener=e.prototype.off;e.prototype.removeAllListeners=e.prototype.off;e.prototype.removeEventListener=e.prototype.off;e.prototype.off=function(c,e){var h,a,b,d,f;if(!this._callbacks||0===arguments.length)return this._callbacks={},this;a=this._callbacks[c];if(!a)return this;if(1===arguments.length)return delete this._callbacks[c], +this;b=d=0;for(f=a.length;d<f;b=++d)if(h=a[b],h===e){a.splice(b,1);break}return this};return e}();k=function(e){function c(a,b){var d,f,g;this.element=a;this.version=c.version;this.defaultOptions.previewTemplate=this.defaultOptions.previewTemplate.replace(/\n*/g,"");this.clickableElements=[];this.listeners=[];this.files=[];"string"===typeof this.element&&(this.element=document.querySelector(this.element));if(!this.element||null==this.element.nodeType)throw Error("Invalid dropzone element.");if(this.element.dropzone)throw Error("Dropzone already attached."); +c.instances.push(this);this.element.dropzone=this;d=null!=(g=c.optionsForElement(this.element))?g:{};this.options=k({},this.defaultOptions,d,null!=b?b:{});if(this.options.forceFallback||!c.isBrowserSupported())return this.options.fallback.call(this);null==this.options.url&&(this.options.url=this.element.getAttribute("action"));if(!this.options.url)throw Error("No URL provided.");if(this.options.acceptedFiles&&this.options.acceptedMimeTypes)throw Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."); +this.options.acceptedMimeTypes&&(this.options.acceptedFiles=this.options.acceptedMimeTypes,delete this.options.acceptedMimeTypes);this.options.method=this.options.method.toUpperCase();(f=this.getExistingFallback())&&f.parentNode&&f.parentNode.removeChild(f);!1!==this.options.previewsContainer&&(this.previewsContainer=this.options.previewsContainer?c.getElement(this.options.previewsContainer,"previewsContainer"):this.element);this.options.clickable&&(this.clickableElements=!0===this.options.clickable? +[this.element]:c.getElements(this.options.clickable,"clickable"));this.init()}var k,h;B(c,e);c.prototype.Emitter=w;c.prototype.events="drop dragstart dragend dragenter dragover dragleave addedfile addedfiles removedfile thumbnail error errormultiple processing processingmultiple uploadprogress totaluploadprogress sending sendingmultiple success successmultiple canceled canceledmultiple complete completemultiple reset maxfilesexceeded maxfilesreached queuecomplete".split(" ");c.prototype.defaultOptions= +{url:null,method:"post",withCredentials:!1,parallelUploads:2,uploadMultiple:!1,maxFilesize:256,paramName:"file",createImageThumbnails:!0,maxThumbnailFilesize:10,thumbnailWidth:120,thumbnailHeight:120,filesizeBase:1E3,maxFiles:null,params:{},clickable:!0,ignoreHiddenFiles:!0,acceptedFiles:null,acceptedMimeTypes:null,autoProcessQueue:!0,autoQueue:!0,addRemoveLinks:!1,previewsContainer:null,hiddenInputContainer:"body",capture:null,dictDefaultMessage:"Drop files here to upload",dictFallbackMessage:"Your browser does not support drag'n'drop file uploads.", +dictFallbackText:"Please use the fallback form below to upload your files like in the olden days.",dictFileTooBig:"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",dictInvalidFileType:"You can't upload files of this type.",dictResponseError:"Server responded with {{statusCode}} code.",dictCancelUpload:"Cancel upload",dictCancelUploadConfirmation:"Are you sure you want to cancel this upload?",dictRemoveFile:"Remove file",dictRemoveFileConfirmation:null,dictMaxFilesExceeded:"You can not upload any more files.", +accept:function(a,b){return b()},init:function(){return l},forceFallback:!1,fallback:function(){var a,b,d,f,g;this.element.className=""+this.element.className+" dz-browser-not-supported";g=this.element.getElementsByTagName("div");d=0;for(f=g.length;d<f;d++)a=g[d],/(^| )dz-message($| )/.test(a.className)&&(b=a,a.className="dz-message");b||(b=c.createElement('<div class="dz-message"><span></span></div>'),this.element.appendChild(b));if(a=b.getElementsByTagName("span")[0])null!=a.textContent?a.textContent= +this.options.dictFallbackMessage:null!=a.innerText&&(a.innerText=this.options.dictFallbackMessage);return this.element.appendChild(this.getFallbackForm())},resize:function(a){var b,d,f;b={srcX:0,srcY:0,srcWidth:a.width,srcHeight:a.height};d=a.width/a.height;b.optWidth=this.options.thumbnailWidth;b.optHeight=this.options.thumbnailHeight;null==b.optWidth&&null==b.optHeight?(b.optWidth=b.srcWidth,b.optHeight=b.srcHeight):null==b.optWidth?b.optWidth=d*b.optHeight:null==b.optHeight&&(b.optHeight=1/d*b.optWidth); +f=b.optWidth/b.optHeight;a.height<b.optHeight||a.width<b.optWidth?(b.trgHeight=b.srcHeight,b.trgWidth=b.srcWidth):d>f?(b.srcHeight=a.height,b.srcWidth=b.srcHeight*f):(b.srcWidth=a.width,b.srcHeight=b.srcWidth/f);b.srcX=(a.width-b.srcWidth)/2;b.srcY=(a.height-b.srcHeight)/2;return b},drop:function(a){return this.element.classList.remove("dz-drag-hover")},dragstart:l,dragend:function(a){return this.element.classList.remove("dz-drag-hover")},dragenter:function(a){return this.element.classList.add("dz-drag-hover")}, +dragover:function(a){return this.element.classList.add("dz-drag-hover")},dragleave:function(a){return this.element.classList.remove("dz-drag-hover")},paste:l,reset:function(){return this.element.classList.remove("dz-started")},addedfile:function(a){var b,d,f,g,m,x;this.element===this.previewsContainer&&this.element.classList.add("dz-started");if(this.previewsContainer){a.previewElement=c.createElement(this.options.previewTemplate.trim());a.previewTemplate=a.previewElement;this.previewsContainer.appendChild(a.previewElement); +g=a.previewElement.querySelectorAll("[data-dz-name]");d=0;for(f=g.length;d<f;d++)b=g[d],b.textContent=a.name;g=a.previewElement.querySelectorAll("[data-dz-size]");d=0;for(f=g.length;d<f;d++)b=g[d],b.innerHTML=this.filesize(a.size);this.options.addRemoveLinks&&(a._removeLink=c.createElement('<a class="dz-remove" href="javascript:undefined;" data-dz-remove>'+this.options.dictRemoveFile+"</a>"),a.previewElement.appendChild(a._removeLink));b=function(b){return function(d){d.preventDefault();d.stopPropagation(); +return a.status===c.UPLOADING?c.confirm(b.options.dictCancelUploadConfirmation,function(){return b.removeFile(a)}):b.options.dictRemoveFileConfirmation?c.confirm(b.options.dictRemoveFileConfirmation,function(){return b.removeFile(a)}):b.removeFile(a)}}(this);m=a.previewElement.querySelectorAll("[data-dz-remove]");x=[];f=0;for(g=m.length;f<g;f++)d=m[f],x.push(d.addEventListener("click",b));return x}},removedfile:function(a){var b;a.previewElement&&null!=(b=a.previewElement)&&b.parentNode.removeChild(a.previewElement); +return this._updateMaxFilesReachedClass()},thumbnail:function(a,b){var d,f,c,m;if(a.previewElement){a.previewElement.classList.remove("dz-file-preview");m=a.previewElement.querySelectorAll("[data-dz-thumbnail]");f=0;for(c=m.length;f<c;f++)d=m[f],d.alt=a.name,d.src=b;return setTimeout(function(b){return function(){return a.previewElement.classList.add("dz-image-preview")}}(this),1)}},error:function(a,b){var d,f,c,m,x;if(a.previewElement){a.previewElement.classList.add("dz-error");"String"!==typeof b&& +b.error&&(b=b.error);m=a.previewElement.querySelectorAll("[data-dz-errormessage]");x=[];f=0;for(c=m.length;f<c;f++)d=m[f],x.push(d.textContent=b);return x}},errormultiple:l,processing:function(a){if(a.previewElement&&(a.previewElement.classList.add("dz-processing"),a._removeLink))return a._removeLink.textContent=this.options.dictCancelUpload},processingmultiple:l,uploadprogress:function(a,b,d){var c,g,m;if(a.previewElement){g=a.previewElement.querySelectorAll("[data-dz-uploadprogress]");m=[];d=0; +for(c=g.length;d<c;d++)a=g[d],"PROGRESS"===a.nodeName?m.push(a.value=b):m.push(a.style.width=""+b+"%");return m}},totaluploadprogress:l,sending:l,sendingmultiple:l,success:function(a){if(a.previewElement)return a.previewElement.classList.add("dz-success")},successmultiple:l,canceled:function(a){return this.emit("error",a,"Upload canceled.")},canceledmultiple:l,complete:function(a){a._removeLink&&(a._removeLink.textContent=this.options.dictRemoveFile);if(a.previewElement)return a.previewElement.classList.add("dz-complete")}, +completemultiple:l,maxfilesexceeded:l,maxfilesreached:l,queuecomplete:l,addedfiles:l,previewTemplate:'<div class="dz-preview dz-file-preview">\n <div class="dz-image"><img data-dz-thumbnail /></div>\n <div class="dz-details">\n <div class="dz-size"><span data-dz-size></span></div>\n <div class="dz-filename"><span data-dz-name></span></div>\n </div>\n <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>\n <div class="dz-error-message"><span data-dz-errormessage></span></div>\n <div class="dz-success-mark">\n <svg width="54px" height="54px" viewBox="0 0 54 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">\n <title>Check</title>\n <defs></defs>\n <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">\n <path d="M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z" id="Oval-2" stroke-opacity="0.198794158" stroke="#747474" fill-opacity="0.816519475" fill="#FFFFFF" sketch:type="MSShapeGroup"></path>\n </g>\n </svg>\n </div>\n <div class="dz-error-mark">\n <svg width="54px" height="54px" viewBox="0 0 54 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">\n <title>Error</title>\n <defs></defs>\n <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">\n <g id="Check-+-Oval-2" sketch:type="MSLayerGroup" stroke="#747474" stroke-opacity="0.198794158" fill="#FFFFFF" fill-opacity="0.816519475">\n <path d="M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z" id="Oval-2" sketch:type="MSShapeGroup"></path>\n </g>\n </g>\n </svg>\n </div>\n</div>'}; +k=function(){var a,b,d,c,g,m,x;c=arguments[0];d=2<=arguments.length?v.call(arguments,1):[];m=0;for(x=d.length;m<x;m++)for(a in b=d[m],b)g=b[a],c[a]=g;return c};c.prototype.getAcceptedFiles=function(){var a,b,d,c,g;c=this.files;g=[];b=0;for(d=c.length;b<d;b++)a=c[b],a.accepted&&g.push(a);return g};c.prototype.getRejectedFiles=function(){var a,b,d,c,g;c=this.files;g=[];b=0;for(d=c.length;b<d;b++)a=c[b],a.accepted||g.push(a);return g};c.prototype.getFilesWithStatus=function(a){var b,d,c,g,m;g=this.files; +m=[];d=0;for(c=g.length;d<c;d++)b=g[d],b.status===a&&m.push(b);return m};c.prototype.getQueuedFiles=function(){return this.getFilesWithStatus(c.QUEUED)};c.prototype.getUploadingFiles=function(){return this.getFilesWithStatus(c.UPLOADING)};c.prototype.getAddedFiles=function(){return this.getFilesWithStatus(c.ADDED)};c.prototype.getActiveFiles=function(){var a,b,d,f,g;f=this.files;g=[];b=0;for(d=f.length;b<d;b++)a=f[b],a.status!==c.UPLOADING&&a.status!==c.QUEUED||g.push(a);return g};c.prototype.init= +function(){var a,b,d,f,g,m;"form"===this.element.tagName&&this.element.setAttribute("enctype","multipart/form-data");this.element.classList.contains("dropzone")&&!this.element.querySelector(".dz-message")&&this.element.appendChild(c.createElement('<div class="dz-default dz-message"><span>'+this.options.dictDefaultMessage+"</span></div>"));this.clickableElements.length&&(d=function(a){return function(){a.hiddenFileInput&&a.hiddenFileInput.parentNode.removeChild(a.hiddenFileInput);a.hiddenFileInput= +document.createElement("input");a.hiddenFileInput.setAttribute("type","file");(null==a.options.maxFiles||1<a.options.maxFiles)&&a.hiddenFileInput.setAttribute("multiple","multiple");a.hiddenFileInput.className="dz-hidden-input";null!=a.options.acceptedFiles&&a.hiddenFileInput.setAttribute("accept",a.options.acceptedFiles);null!=a.options.capture&&a.hiddenFileInput.setAttribute("capture",a.options.capture);a.hiddenFileInput.style.visibility="hidden";a.hiddenFileInput.style.position="absolute";a.hiddenFileInput.style.top= +"0";a.hiddenFileInput.style.left="0";a.hiddenFileInput.style.height="0";a.hiddenFileInput.style.width="0";document.querySelector(a.options.hiddenInputContainer).appendChild(a.hiddenFileInput);return a.hiddenFileInput.addEventListener("change",function(){var b,c,f,g;c=a.hiddenFileInput.files;if(c.length)for(f=0,g=c.length;f<g;f++)b=c[f],a.addFile(b);a.emit("addedfiles",c);return d()})}}(this),d());this.URL=null!=(a=window.URL)?a:window.webkitURL;m=this.events;f=0;for(g=m.length;f<g;f++)a=m[f],this.on(a, +this.options[a]);this.on("uploadprogress",function(a){return function(){return a.updateTotalUploadProgress()}}(this));this.on("removedfile",function(a){return function(){return a.updateTotalUploadProgress()}}(this));this.on("canceled",function(a){return function(b){return a.emit("complete",b)}}(this));this.on("complete",function(a){return function(b){if(0===a.getAddedFiles().length&&0===a.getUploadingFiles().length&&0===a.getQueuedFiles().length)return setTimeout(function(){return a.emit("queuecomplete")}, +0)}}(this));b=function(a){a.stopPropagation();return a.preventDefault?a.preventDefault():a.returnValue=!1};this.listeners=[{element:this.element,events:{dragstart:function(a){return function(b){return a.emit("dragstart",b)}}(this),dragenter:function(a){return function(d){b(d);return a.emit("dragenter",d)}}(this),dragover:function(a){return function(d){var c;try{c=d.dataTransfer.effectAllowed}catch(f){}d.dataTransfer.dropEffect="move"===c||"linkMove"===c?"move":"copy";b(d);return a.emit("dragover", +d)}}(this),dragleave:function(a){return function(b){return a.emit("dragleave",b)}}(this),drop:function(a){return function(d){b(d);return a.drop(d)}}(this),dragend:function(a){return function(b){return a.emit("dragend",b)}}(this)}}];this.clickableElements.forEach(function(a){return function(b){return a.listeners.push({element:b,events:{click:function(d){(b!==a.element||d.target===a.element||c.elementInside(d.target,a.element.querySelector(".dz-message")))&&a.hiddenFileInput.click();return!0}}})}}(this)); +this.enable();return this.options.init.call(this)};c.prototype.destroy=function(){var a;this.disable();this.removeAllFiles(!0);null!=(a=this.hiddenFileInput)&&a.parentNode&&(this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput),this.hiddenFileInput=null);delete this.element.dropzone;return c.instances.splice(c.instances.indexOf(this),1)};c.prototype.updateTotalUploadProgress=function(){var a,b,d,c,g,m;b=d=0;if(this.getActiveFiles().length){m=this.getActiveFiles();c=0;for(g=m.length;c< +g;c++)a=m[c],d+=a.upload.bytesSent,b+=a.upload.total;a=100*d/b}else a=100;return this.emit("totaluploadprogress",a,b,d)};c.prototype._getParamName=function(a){return"function"===typeof this.options.paramName?this.options.paramName(a):""+this.options.paramName+(this.options.uploadMultiple?"["+a+"]":"")};c.prototype.getFallbackForm=function(){var a,b;if(a=this.getExistingFallback())return a;a='<div class="dz-fallback">';this.options.dictFallbackText&&(a+="<p>"+this.options.dictFallbackText+"</p>"); +a+='<input type="file" name="'+this._getParamName(0)+'" '+(this.options.uploadMultiple?'multiple="multiple"':void 0)+' /><input type="submit" value="Upload!"></div>';a=c.createElement(a);"FORM"!==this.element.tagName?(b=c.createElement('<form action="'+this.options.url+'" enctype="multipart/form-data" method="'+this.options.method+'"></form>'),b.appendChild(a)):(this.element.setAttribute("enctype","multipart/form-data"),this.element.setAttribute("method",this.options.method));return null!=b?b:a}; +c.prototype.getExistingFallback=function(){var a,b,d,c,g;b=function(a){var b,d,c;d=0;for(c=a.length;d<c;d++)if(b=a[d],/(^| )fallback($| )/.test(b.className))return b};g=["div","form"];d=0;for(c=g.length;d<c;d++)if(a=g[d],a=b(this.element.getElementsByTagName(a)))return a};c.prototype.setupEventListeners=function(){var a,b,d,c,g,m,e;m=this.listeners;e=[];c=0;for(g=m.length;c<g;c++)a=m[c],e.push(function(){var c,f;c=a.events;f=[];for(b in c)d=c[b],f.push(a.element.addEventListener(b,d,!1));return f}()); +return e};c.prototype.removeEventListeners=function(){var a,b,c,f,g,e,h;e=this.listeners;h=[];f=0;for(g=e.length;f<g;f++)a=e[f],h.push(function(){var f,g;f=a.events;g=[];for(b in f)c=f[b],g.push(a.element.removeEventListener(b,c,!1));return g}());return h};c.prototype.disable=function(){var a,b,c,f,g;this.clickableElements.forEach(function(a){return a.classList.remove("dz-clickable")});this.removeEventListeners();f=this.files;g=[];b=0;for(c=f.length;b<c;b++)a=f[b],g.push(this.cancelUpload(a));return g}; +c.prototype.enable=function(){this.clickableElements.forEach(function(a){return a.classList.add("dz-clickable")});return this.setupEventListeners()};c.prototype.filesize=function(a){var b,c,f,g,e,h,k,u;f=0;g="b";if(0<a){h=["TB","GB","MB","KB","b"];c=k=0;for(u=h.length;k<u;c=++k)if(e=h[c],b=Math.pow(this.options.filesizeBase,4-c)/10,a>=b){f=a/Math.pow(this.options.filesizeBase,4-c);g=e;break}f=Math.round(10*f)/10}return"<strong>"+f+"</strong> "+g};c.prototype._updateMaxFilesReachedClass=function(){return null!= +this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit("maxfilesreached",this.files),this.element.classList.add("dz-max-files-reached")):this.element.classList.remove("dz-max-files-reached")};c.prototype.drop=function(a){var b;a.dataTransfer&&(this.emit("drop",a),b=a.dataTransfer.files,this.emit("addedfiles",b),b.length&&((a=a.dataTransfer.items)&&a.length&&null!=a[0].webkitGetAsEntry?this._addFilesFromItems(a): +this.handleFiles(b)))};c.prototype.paste=function(a){var b;if(null!=(null!=a?null!=(b=a.clipboardData)?b.items:void 0:void 0)&&(this.emit("paste",a),a=a.clipboardData.items,a.length))return this._addFilesFromItems(a)};c.prototype.handleFiles=function(a){var b,c,f,g;g=[];c=0;for(f=a.length;c<f;c++)b=a[c],g.push(this.addFile(b));return g};c.prototype._addFilesFromItems=function(a){var b,c,f,g,e;e=[];f=0;for(g=a.length;f<g;f++)c=a[f],null!=c.webkitGetAsEntry&&(b=c.webkitGetAsEntry())?b.isFile?e.push(this.addFile(c.getAsFile())): +b.isDirectory?e.push(this._addFilesFromDirectory(b,b.name)):e.push(void 0):null!=c.getAsFile?null==c.kind||"file"===c.kind?e.push(this.addFile(c.getAsFile())):e.push(void 0):e.push(void 0);return e};c.prototype._addFilesFromDirectory=function(a,b){var c,f;c=a.createReader();f=function(a){return function(c){var d,f,e;f=0;for(e=c.length;f<e;f++)d=c[f],d.isFile?d.file(function(c){if(!a.options.ignoreHiddenFiles||"."!==c.name.substring(0,1))return c.fullPath=""+b+"/"+c.name,a.addFile(c)}):d.isDirectory&& +a._addFilesFromDirectory(d,""+b+"/"+d.name)}}(this);return c.readEntries(f,function(a){return"undefined"!==typeof console&&null!==console?"function"===typeof console.log?console.log(a):void 0:void 0})};c.prototype.accept=function(a,b){return a.size>1048576*this.options.maxFilesize?b(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(a.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize)):c.isValidFile(a,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>= +this.options.maxFiles?(b(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles)),this.emit("maxfilesexceeded",a)):this.options.accept.call(this,a,b):b(this.options.dictInvalidFileType)};c.prototype.addFile=function(a){a.upload={progress:0,total:a.size,bytesSent:0};this.files.push(a);a.status=c.ADDED;this.emit("addedfile",a);this._enqueueThumbnail(a);return this.accept(a,function(b){return function(c){c?(a.accepted=!1,b._errorProcessing([a],c)):(a.accepted=!0,b.options.autoQueue&& +b.enqueueFile(a));return b._updateMaxFilesReachedClass()}}(this))};c.prototype.enqueueFiles=function(a){var b,c,f;c=0;for(f=a.length;c<f;c++)b=a[c],this.enqueueFile(b);return null};c.prototype.enqueueFile=function(a){if(a.status===c.ADDED&&!0===a.accepted){if(a.status=c.QUEUED,this.options.autoProcessQueue)return setTimeout(function(a){return function(){return a.processQueue()}}(this),0)}else throw Error("This file can't be queued because it has already been processed or was rejected.");};c.prototype._thumbnailQueue= +[];c.prototype._processingThumbnail=!1;c.prototype._enqueueThumbnail=function(a){if(this.options.createImageThumbnails&&a.type.match(/image.*/)&&a.size<=1048576*this.options.maxThumbnailFilesize)return this._thumbnailQueue.push(a),setTimeout(function(a){return function(){return a._processThumbnailQueue()}}(this),0)};c.prototype._processThumbnailQueue=function(){if(!this._processingThumbnail&&0!==this._thumbnailQueue.length)return this._processingThumbnail=!0,this.createThumbnail(this._thumbnailQueue.shift(), +function(a){return function(){a._processingThumbnail=!1;return a._processThumbnailQueue()}}(this))};c.prototype.removeFile=function(a){a.status===c.UPLOADING&&this.cancelUpload(a);this.files=r(this.files,a);this.emit("removedfile",a);if(0===this.files.length)return this.emit("reset")};c.prototype.removeAllFiles=function(a){var b,d,f,g;null==a&&(a=!1);g=this.files.slice();d=0;for(f=g.length;d<f;d++)b=g[d],(b.status!==c.UPLOADING||a)&&this.removeFile(b);return null};c.prototype.createThumbnail=function(a, +b){var c;c=new FileReader;c.onload=function(f){return function(){if("image/svg+xml"===a.type)f.emit("thumbnail",a,c.result),null!=b&&b();else return f.createThumbnailFromUrl(a,c.result,b)}}(this);return c.readAsDataURL(a)};c.prototype.createThumbnailFromUrl=function(a,b,c,f){var g;g=document.createElement("img");f&&(g.crossOrigin=f);g.onload=function(b){return function(){var f,e,h,k,u,l,n;a.width=g.width;a.height=g.height;h=b.options.resize.call(b,a);null==h.trgWidth&&(h.trgWidth=h.optWidth);null== +h.trgHeight&&(h.trgHeight=h.optHeight);f=document.createElement("canvas");e=f.getContext("2d");f.width=h.trgWidth;f.height=h.trgHeight;p(e,g,null!=(k=h.srcX)?k:0,null!=(u=h.srcY)?u:0,h.srcWidth,h.srcHeight,null!=(l=h.trgX)?l:0,null!=(n=h.trgY)?n:0,h.trgWidth,h.trgHeight);f=f.toDataURL("image/png");b.emit("thumbnail",a,f);if(null!=c)return c()}}(this);null!=c&&(g.onerror=c);return g.src=b};c.prototype.processQueue=function(){var a,b,c,f;b=this.options.parallelUploads;a=c=this.getUploadingFiles().length; +if(!(c>=b)&&(f=this.getQueuedFiles(),0<f.length)){if(this.options.uploadMultiple)return this.processFiles(f.slice(0,b-c));for(;a<b&&f.length;)this.processFile(f.shift()),a++}};c.prototype.processFile=function(a){return this.processFiles([a])};c.prototype.processFiles=function(a){var b,d,f;d=0;for(f=a.length;d<f;d++)b=a[d],b.processing=!0,b.status=c.UPLOADING,this.emit("processing",b);this.options.uploadMultiple&&this.emit("processingmultiple",a);return this.uploadFiles(a)};c.prototype._getFilesWithXhr= +function(a){var b,c,f,g,e;g=this.files;e=[];c=0;for(f=g.length;c<f;c++)b=g[c],b.xhr===a&&e.push(b);return e};c.prototype.cancelUpload=function(a){var b,d,f,g;if(a.status===c.UPLOADING){d=this._getFilesWithXhr(a.xhr);f=0;for(g=d.length;f<g;f++)b=d[f],b.status=c.CANCELED;a.xhr.abort();a=0;for(f=d.length;a<f;a++)b=d[a],this.emit("canceled",b);this.options.uploadMultiple&&this.emit("canceledmultiple",d)}else if((b=a.status)===c.ADDED||b===c.QUEUED)a.status=c.CANCELED,this.emit("canceled",a),this.options.uploadMultiple&& +this.emit("canceledmultiple",[a]);if(this.options.autoProcessQueue)return this.processQueue()};h=function(){var a,b;b=arguments[0];a=2<=arguments.length?v.call(arguments,1):[];return"function"===typeof b?b.apply(this,a):b};c.prototype.uploadFile=function(a){return this.uploadFiles([a])};c.prototype.uploadFiles=function(a){var b,d,f,g,e,l,p,n,q,r,w,v,t,z,y;t=new XMLHttpRequest;e=0;for(v=a.length;e<v;e++)b=a[e],b.xhr=t;e=h(this.options.method,a);v=h(this.options.url,a);t.open(e,v,!0);t.withCredentials= +!!this.options.withCredentials;r=null;f=function(c){return function(){var d,f,e;e=[];d=0;for(f=a.length;d<f;d++)b=a[d],e.push(c._errorProcessing(a,r||c.options.dictResponseError.replace("{{statusCode}}",t.status),t));return e}}(this);w=function(c){return function(d){var f,e,g;if(null!=d)for(f=100*d.loaded/d.total,e=0,g=a.length;e<g;e++)b=a[e],b.upload={progress:f,total:d.total,bytesSent:d.loaded};else{d=!0;f=100;e=0;for(g=a.length;e<g;e++){b=a[e];if(100!==b.upload.progress||b.upload.bytesSent!==b.upload.total)d= +!1;b.upload.progress=f;b.upload.bytesSent=b.upload.total}if(d)return}g=[];d=0;for(e=a.length;d<e;d++)b=a[d],g.push(c.emit("uploadprogress",b,f,b.upload.bytesSent));return g}}(this);t.onload=function(b){return function(d){var e;if(a[0].status!==c.CANCELED&&4===t.readyState){r=t.responseText;if(t.getResponseHeader("content-type")&&~t.getResponseHeader("content-type").indexOf("application/json"))try{r=JSON.parse(r)}catch(g){d=g,r="Invalid JSON response from server."}w();return 200<=(e=t.status)&&300> +e?b._finished(a,r,d):f()}}}(this);t.onerror=function(b){return function(){if(a[0].status!==c.CANCELED)return f()}}(this);(null!=(g=t.upload)?g:t).onprogress=w;e={Accept:"application/json","Cache-Control":"no-cache","X-Requested-With":"XMLHttpRequest"};this.options.headers&&k(e,this.options.headers);for(d in e)(g=e[d])&&t.setRequestHeader(d,g);d=new FormData;if(this.options.params)for(n in e=this.options.params,e)g=e[n],d.append(n,g);n=0;for(g=a.length;n<g;n++)b=a[n],this.emit("sending",b,t,d);this.options.uploadMultiple&& +this.emit("sendingmultiple",a,t,d);if("FORM"===this.element.tagName)for(v=this.element.querySelectorAll("input, textarea, select, button"),g=0,e=v.length;g<e;g++)if(p=v[g],n=p.getAttribute("name"),q=p.getAttribute("type"),"SELECT"===p.tagName&&p.hasAttribute("multiple"))for(y=p.options,q=0,z=y.length;q<z;q++)p=y[q],p.selected&&d.append(n,p.value);else(!q||"checkbox"!==(l=q.toLowerCase())&&"radio"!==l||p.checked)&&d.append(n,p.value);l=n=0;for(g=a.length-1;0<=g?n<=g:n>=g;l=0<=g?++n:--n)d.append(this._getParamName(l), +a[l],a[l].name);return this.submitRequest(t,d,a)};c.prototype.submitRequest=function(a,b,c){return a.send(b)};c.prototype._finished=function(a,b,d){var f,e,h;e=0;for(h=a.length;e<h;e++)f=a[e],f.status=c.SUCCESS,this.emit("success",f,b,d),this.emit("complete",f);this.options.uploadMultiple&&(this.emit("successmultiple",a,b,d),this.emit("completemultiple",a));if(this.options.autoProcessQueue)return this.processQueue()};c.prototype._errorProcessing=function(a,b,d){var e,g,h;g=0;for(h=a.length;g<h;g++)e= +a[g],e.status=c.ERROR,this.emit("error",e,b,d),this.emit("complete",e);this.options.uploadMultiple&&(this.emit("errormultiple",a,b,d),this.emit("completemultiple",a));if(this.options.autoProcessQueue)return this.processQueue()};return c}(w);k.version="4.2.0";k.options={};k.optionsForElement=function(e){if(e.getAttribute("id"))return k.options[q(e.getAttribute("id"))]};k.instances=[];k.forElement=function(e){"string"===typeof e&&(e=document.querySelector(e));if(null==(null!=e?e.dropzone:void 0))throw Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone."); +return e.dropzone};k.autoDiscover=!0;k.discover=function(){var e,c,u,h,a;document.querySelectorAll?c=document.querySelectorAll(".dropzone"):(c=[],e=function(a){var d,e,g,h;h=[];e=0;for(g=a.length;e<g;e++)d=a[e],/(^| )dropzone($| )/.test(d.className)?h.push(c.push(d)):h.push(void 0);return h},e(document.getElementsByTagName("div")),e(document.getElementsByTagName("form")));a=[];u=0;for(h=c.length;u<h;u++)e=c[u],!1!==k.optionsForElement(e)?a.push(new k(e)):a.push(void 0);return a};k.blacklistedBrowsers= +[/opera.*(Windows Phone|Macintosh).*version\/12/i];k.isBrowserSupported=function(){var e,c,u,h,a;e=!0;if(window.File&&window.FileReader&&window.FileList&&window.Blob&&window.FormData&&document.querySelector)if("classList"in document.createElement("a"))for(a=k.blacklistedBrowsers,u=0,h=a.length;u<h;u++)c=a[u],c.test(navigator.userAgent)&&(e=!1);else e=!1;else e=!1;return e};r=function(e,c){var k,h,a,b;b=[];h=0;for(a=e.length;h<a;h++)k=e[h],k!==c&&b.push(k);return b};q=function(e){return e.replace(/[\-_](\w)/g, +function(c){return c.charAt(1).toUpperCase()})};k.createElement=function(e){var c;c=document.createElement("div");c.innerHTML=e;return c.childNodes[0]};k.elementInside=function(e,c){if(e===c)return!0;for(;e=e.parentNode;)if(e===c)return!0;return!1};k.getElement=function(e,c){var k;"string"===typeof e?k=document.querySelector(e):null!=e.nodeType&&(k=e);if(null==k)throw Error("Invalid `"+c+"` option provided. Please provide a CSS selector or a plain HTML element.");return k};k.getElements=function(e, +c){var k,h,a,b,d;if(e instanceof Array){h=[];try{for(a=0,b=e.length;a<b;a++)k=e[a],h.push(this.getElement(k,c))}catch(f){h=null}}else if("string"===typeof e)for(h=[],d=document.querySelectorAll(e),a=0,b=d.length;a<b;a++)k=d[a],h.push(k);else null!=e.nodeType&&(h=[e]);if(null==h||!h.length)throw Error("Invalid `"+c+"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");return h};k.confirm=function(e,c,k){if(window.confirm(e))return c();if(null!=k)return k()}; +k.isValidFile=function(e,c){var k,h,a,b,d;if(!c)return!0;c=c.split(",");h=e.type;k=h.replace(/\/.*$/,"");b=0;for(d=c.length;b<d;b++)if(a=c[b],a=a.trim(),"."===a.charAt(0)){if(-1!==e.name.toLowerCase().indexOf(a.toLowerCase(),e.name.length-a.length))return!0}else if(/\/\*$/.test(a)){if(k===a.replace(/\/.*$/,""))return!0}else if(h===a)return!0;return!1};"undefined"!==typeof jQuery&&null!==jQuery&&(jQuery.fn.dropzone=function(e){return this.each(function(){return new k(this,e)})});"undefined"!==typeof module&& +null!==module?module.exports=k:window.Dropzone=k;k.ADDED="added";k.QUEUED="queued";k.ACCEPTED=k.QUEUED;k.UPLOADING="uploading";k.PROCESSING=k.UPLOADING;k.CANCELED="canceled";k.ERROR="error";k.SUCCESS="success";n=function(e){var c,k,h,a,b;h=e.naturalHeight;c=document.createElement("canvas");c.width=1;c.height=h;c=c.getContext("2d");c.drawImage(e,0,0);c=c.getImageData(0,0,1,h).data;b=0;for(a=k=h;a>b;)e=c[4*(a-1)+3],0===e?k=a:b=a,a=k+b>>1;h=a/h;return 0===h?1:h};p=function(e,c,k,h,a,b,d,f,g,m){var l; +l=n(c);m/=l;l=0;switch(EXIF.getData(c)){case 3:l=2;break;case 6:l=1;break;case 8:l=-1}l&&(e.translate(d+g/2,f+m/2),e.rotate(l*Math.PI/2),d=-g/2,f=-m/2);return e.drawImage(c,k,h,a,b,d,f,g,m)};k._autoDiscoverFunction=function(){if(k.autoDiscover)return k.discover()};(function(e,c){var k,h,a,b,d,f,g,l,n;a=!1;n=!0;h=e.document;l=h.documentElement;k=h.addEventListener?"addEventListener":"attachEvent";g=h.addEventListener?"removeEventListener":"detachEvent";f=h.addEventListener?"":"on";b=function(d){if("readystatechange"!== +d.type||"complete"===h.readyState)if(("load"===d.type?e:h)[g](f+d.type,b,!1),!a&&(a=!0))return c.call(e,d.type||d)};d=function(){try{l.doScroll("left")}catch(a){setTimeout(d,50);return}return b("poll")};if("complete"!==h.readyState){if(h.createEventObject&&l.doScroll){try{n=!e.frameElement}catch(p){}n&&d()}h[k](f+"DOMContentLoaded",b,!1);h[k](f+"readystatechange",b,!1);return e[k](f+"load",b,!1)}})(window,k._autoDiscoverFunction)}).call(this); diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js index 267643898..d1dba631e 100644 --- a/web/js/map-OpenLayers.js +++ b/web/js/map-OpenLayers.js @@ -646,6 +646,17 @@ OpenLayers.Protocol.FixMyStreet = OpenLayers.Class(OpenLayers.Protocol.HTTP, { /* Pan data handler */ OpenLayers.Format.FixMyStreet = OpenLayers.Class(OpenLayers.Format.JSON, { read: function(json, filter) { + // Check we haven't received the data after the map has been clicked. + if (fixmystreet.page == 'new') { + // If we have, we want to do nothing, which means returning an + // array of the back-projected version of the current pin + var pin = fixmystreet.markers.features[0].clone(); + pin.geometry.transform( + fixmystreet.map.getProjectionObject(), + new OpenLayers.Projection("EPSG:4326") + ); + return [ pin ]; + } if (typeof json == 'string') { obj = OpenLayers.Format.JSON.prototype.read.apply(this, [json, filter]); } else { diff --git a/web/js/src/exif.js b/web/js/src/exif.js new file mode 100644 index 000000000..3a2c7e1c3 --- /dev/null +++ b/web/js/src/exif.js @@ -0,0 +1,94 @@ +/* Cut down version of https://github.com/exif-js/exif-js + * only looking for orientation EXIF data. MIT. */ + +(function() { + var EXIF = {}; + window.EXIF = EXIF; + + function readEXIFData(file, start) { + var str = ""; + for (var n = start; n < start+4; n++) { + str += String.fromCharCode(file.getUint8(n)); + } + if (str != "Exif") { + return false; + } + + var bigEnd, + tiffOffset = start + 6; + + // test for TIFF validity and endianness + if (file.getUint16(tiffOffset) == 0x4949) { + bigEnd = false; + } else if (file.getUint16(tiffOffset) == 0x4D4D) { + bigEnd = true; + } else { + return false; + } + + if (file.getUint16(tiffOffset+2, !bigEnd) != 0x002A) { + return false; + } + + var firstIFDOffset = file.getUint32(tiffOffset+4, !bigEnd); + if (firstIFDOffset < 0x00000008) { + return false; + } + + var dirStart = tiffOffset + firstIFDOffset, + entries = file.getUint16(dirStart, !bigEnd), + tags = {}, + entryOffset, + i; + + for (i=0;i<entries;i++) { + entryOffset = dirStart + i*12 + 2; + if (file.getUint16(entryOffset, !bigEnd) == 0x0112) { + return parseInt(file.getUint16(entryOffset + 8, !bigEnd), 10); + } + } + return false; + } + + EXIF.getData = function(img) { + if ((img instanceof Image || img instanceof HTMLImageElement) && !img.complete) { + return false; + } + + var base64 = img.src.replace(/^data\:([^\;]+)\;base64,/gmi, ''); + var binary = atob(base64); + var len = binary.length; + var file = new ArrayBuffer(len); + var view = new Uint8Array(file); + for (var i = 0; i < len; i++) { + view[i] = binary.charCodeAt(i); + } + + var dataView = new DataView(file); + if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) { + return false; // not a valid jpeg + } + + var offset = 2, + length = file.byteLength, + marker; + + while (offset < length) { + if (dataView.getUint8(offset) != 0xFF) { + return false; // not a valid marker, something is wrong + } + + marker = dataView.getUint8(offset + 1); + + // we could implement handling for other markers here, + // but we're only looking for 0xFFE1 for EXIF data + if (marker == 225) { + return readEXIFData(dataView, offset + 4); + // offset += 2 + file.getShortAt(offset+2, true); + } else { + offset += 2 + dataView.getUint16(offset+2); + } + } + }; + +})(); |