diff options
Diffstat (limited to 'perllib/FixMyStreet/App/Controller/Photo.pm')
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Photo.pm | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Photo.pm b/perllib/FixMyStreet/App/Controller/Photo.pm index 8711b19e9..a84c538cc 100644 --- a/perllib/FixMyStreet/App/Controller/Photo.pm +++ b/perllib/FixMyStreet/App/Controller/Photo.pm @@ -5,6 +5,7 @@ use namespace::autoclean; BEGIN {extends 'Catalyst::Controller'; } use DateTime::Format::HTTP; +use Digest::SHA1 qw(sha1_hex); use Path::Class; =head1 NAME @@ -36,7 +37,7 @@ sub during :LocalRegex('^([0-9a-f]{40})\.temp\.jpeg$') { if ( $c->cobrand->default_photo_resize ) { $photo = _shrink( $photo, $c->cobrand->default_photo_resize ); } else { - $photo = _shrink( $photo, 'x250' ); + $photo = _shrink( $photo, '250x250' ); } $c->forward( 'output', [ $photo ] ); @@ -85,7 +86,7 @@ sub index :LocalRegex('^(c/)?(\d+)(?:\.(full|tn|fp))?\.jpeg$') { } elsif ( $c->cobrand->default_photo_resize ) { $photo = _shrink( $photo, $c->cobrand->default_photo_resize ); } else { - $photo = _shrink( $photo, 'x250' ); + $photo = _shrink( $photo, '250x250' ); } $c->forward( 'output', [ $photo ] ); @@ -114,6 +115,7 @@ sub _shrink { $image->BlobToImage($photo); my $err = $image->Scale(geometry => "$size>"); throw Error::Simple("resize failed: $err") if "$err"; + $image->Strip(); my @blobs = $image->ImageToBlob(); undef $image; return $blobs[0]; @@ -129,11 +131,101 @@ sub _crop { throw Error::Simple("resize failed: $err") if "$err"; $err = $image->Extent( geometry => '90x60', gravity => 'Center' ); throw Error::Simple("resize failed: $err") if "$err"; + $image->Strip(); my @blobs = $image->ImageToBlob(); undef $image; return $blobs[0]; } +=head2 process_photo + +Handle the photo - either checking and storing it after an upload or retrieving +it from the cache. + +Store any error message onto 'photo_error' in stash. +=cut + +sub process_photo : Private { + my ( $self, $c ) = @_; + + return + $c->forward('process_photo_upload') + || $c->forward('process_photo_cache') + || 1; # always return true +} + +sub process_photo_upload : Private { + my ( $self, $c ) = @_; + + # check for upload or return + my $upload = $c->req->upload('photo') + || return; + + # check that the photo is a jpeg + my $ct = $upload->type; + $ct =~ s/x-citrix-//; # Thanks, Citrix + # Had a report of a JPEG from an Android 2.1 coming through as a byte stream + unless ( $ct eq 'image/jpeg' || $ct eq 'image/pjpeg' || $ct eq 'application/octet-stream' ) { + $c->stash->{photo_error} = _('Please upload a JPEG image only'); + return; + } + + # get the photo into a variable + my $photo_blob = eval { + my $filename = $upload->tempname; + my $out = `jhead -se -autorot $filename 2>&1`; + die _("Please upload a JPEG image only"."\n") if $out =~ /Not JPEG:/; + my $photo = $upload->slurp; + return $photo; + }; + if ( my $error = $@ ) { + my $format = _( +"That image doesn't appear to have uploaded correctly (%s), please try again." + ); + $c->stash->{photo_error} = sprintf( $format, $error ); + return; + } + + # we have an image we can use - save it to the upload dir for storage + my $cache_dir = dir( $c->config->{UPLOAD_DIR} ); + $cache_dir->mkpath; + unless ( -d $cache_dir && -w $cache_dir ) { + warn "Can't find/write to photo cache directory '$cache_dir'"; + return; + } + + my $fileid = sha1_hex($photo_blob); + $upload->copy_to( file($cache_dir, $fileid . '.jpeg') ); + + # stick the hash on the stash, so don't have to reupload in case of error + $c->stash->{upload_fileid} = $fileid; + + return 1; +} + +=head2 process_photo_cache + +Look for the upload_fileid parameter and check it matches a file on disk. If it +does return true and put fileid on stash, otherwise false. + +=cut + +sub process_photo_cache : Private { + my ( $self, $c ) = @_; + + # get the fileid and make sure it is just a hex number + my $fileid = $c->req->param('upload_fileid') || ''; + $fileid =~ s{[^0-9a-f]}{}gi; + return unless $fileid; + + my $file = file( $c->config->{UPLOAD_DIR}, "$fileid.jpeg" ); + return unless -e $file; + + $c->stash->{upload_fileid} = $fileid; + return 1; +} + + =head1 AUTHOR Struan Donald |