X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=tools%2Fpicture-upload.pl;h=c708f7f24478b159099f0a3187cbc2aee52a36f0;hb=0b66310580e71223bc66168a8ee3b2c8e7299b5d;hp=af3012ab1973f024101b86b6a13da61135b144b8;hpb=e20270fec4f6d34f01050bea4c5765d5b3c4ed33;p=koha-ffzg.git diff --git a/tools/picture-upload.pl b/tools/picture-upload.pl index af3012ab19..c708f7f244 100755 --- a/tools/picture-upload.pl +++ b/tools/picture-upload.pl @@ -3,18 +3,18 @@ # # This file is part of Koha. # -# Koha is free software; you can redistribute it and/or modify it under the -# terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. # -# Koha is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. # -# You should have received a copy of the GNU General Public License along with -# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, -# Suite 330, Boston, MA 02111-1307 USA +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . # # # @@ -22,29 +22,36 @@ use Modern::Perl; use File::Temp; -use File::Copy; use CGI qw ( -utf8 ); use GD; use C4::Context; -use C4::Auth; -use C4::Output; +use C4::Auth qw( get_template_and_user ); +use C4::Output qw( output_and_exit output_html_with_http_headers ); use C4::Members; -use C4::Debug; -my $input = new CGI; +use Koha::Logger; +use Koha::Patrons; +use Koha::Patron::Images; +use Koha::Token; + +my $input = CGI->new; + +unless (C4::Context->preference('patronimages')) { + # redirect to intranet home if patronimages is not enabled + print $input->redirect("/cgi-bin/koha/mainpage.pl"); + exit; +} my ($template, $loggedinuser, $cookie) = get_template_and_user({template_name => "tools/picture-upload.tt", query => $input, type => "intranet", - authnotrequired => 0, flagsrequired => { tools => 'batch_upload_patron_images'}, - debug => 0, }); -my $filetype = $input->param('filetype'); +our $filetype = $input->param('filetype') || ''; my $cardnumber = $input->param('cardnumber'); -my $uploadfilename = $input->param('uploadfile'); +our $uploadfilename = $input->param('uploadfile') || ''; my $uploadfile = $input->upload('uploadfile'); my $borrowernumber = $input->param('borrowernumber'); my $op = $input->param('op') || ''; @@ -53,7 +60,8 @@ my $op = $input->param('op') || ''; # Other parts of this code could be optimized as well, I think. Perhaps the file upload could be done with YUI's upload # coded. -fbcit -$debug and warn "Params are: filetype=$filetype, cardnumber=$cardnumber, borrowernumber=$borrowernumber, uploadfile=$uploadfilename"; +our $logger = Koha::Logger->get; +$logger->debug("Params are: filetype=$filetype, cardnumber=$cardnumber, borrowernumber=$borrowernumber, uploadfile=$uploadfilename"); =head1 NAME @@ -70,21 +78,26 @@ Files greater than 100K will be refused. Images should be 140x200 pixels. If the =cut -$debug and warn "Operation requested: $op"; - -my ( $total, $handled, @counts, $tempfile, $tfh, %errors ); +my ( $total, $handled, $tempfile, $tfh ); +our @counts = (); +our %errors = (); # Case is important in these operational values as the template must use case to be visually pleasing! if ( ( $op eq 'Upload' ) && $uploadfile ) { + + output_and_exit( $input, $cookie, $template, 'wrong_csrf_token' ) + unless Koha::Token->new->check_csrf({ + session_id => scalar $input->cookie('CGISESSID'), + token => scalar $input->param('csrf_token'), + }); + my $dirname = File::Temp::tempdir( CLEANUP => 1 ); - $debug and warn "dirname = $dirname"; my $filesuffix; if ( $uploadfilename =~ m/(\..+)$/i ) { $filesuffix = $1; } ( $tfh, $tempfile ) = File::Temp::tempfile( SUFFIX => $filesuffix, UNLINK => 1 ); - $debug and warn "tempfile = $tempfile"; my ( @directories, $results ); $errors{'NOTZIP'} = 1 @@ -102,7 +115,9 @@ if ( ( $op eq 'Upload' ) && $uploadfile ) { } close $tfh; if ( $filetype eq 'zip' ) { - unless ( system( "unzip", $tempfile, '-d', $dirname ) == 0 ) { + qx/unzip $tempfile -d $dirname/; + my $exit_code = $?; + unless ( $exit_code == 0 ) { $errors{'UZIPFAIL'} = $uploadfilename; $template->param( ERRORS => [ \%errors ] ); # This error is fatal to the import, so bail out here @@ -115,7 +130,6 @@ if ( ( $op eq 'Upload' ) && $uploadfile ) { while ( my $entry = readdir RECDIR ) { push @directories, "$recursive_dir/$entry" if ( -d "$recursive_dir/$entry" and $entry !~ /^\./ ); - $debug and warn "$recursive_dir/$entry"; } closedir RECDIR; } @@ -139,8 +153,8 @@ if ( ( $op eq 'Upload' ) && $uploadfile ) { else { my $filecount; map { $filecount += $_->{count} } @counts; - $debug and warn "Total directories processed: $total"; - $debug and warn "Total files processed: $filecount"; + $logger->debug("Total directories processed: $total"); + $logger->debug("Total files processed: $filecount"); $template->param( TOTAL => $total, HANDLED => $handled, @@ -157,34 +171,49 @@ elsif ( ( $op eq 'Upload' ) && !$uploadfile ) { $template->param( filetype => $filetype ); } elsif ( $op eq 'Delete' ) { - my $dberror = RmPatronImage($cardnumber); - $debug and warn "Patron image deleted for $cardnumber"; - warn "Database returned $dberror" if $dberror; + output_and_exit( $input, $cookie, $template, 'wrong_csrf_token' ) + unless Koha::Token->new->check_csrf({ + session_id => scalar $input->cookie('CGISESSID'), + token => scalar $input->param('csrf_token'), + }); + + my $deleted = eval { + Koha::Patron::Images->find( $borrowernumber )->delete; + }; + if ( $@ or not $deleted ) { + warn "Image for patron '$borrowernumber' has not been deleted"; + } } if ( $borrowernumber && !%errors && !$template->param('ERRORS') ) { print $input->redirect( "/cgi-bin/koha/members/moremember.pl?borrowernumber=$borrowernumber"); } else { + $template->param( + csrf_token => Koha::Token->new->generate_csrf({ + session_id => scalar $input->cookie('CGISESSID'), + }), + ); output_html_with_http_headers $input, $cookie, $template->output; } sub handle_dir { my ( $dir, $suffix, $template, $cardnumber, $source ) = @_; my ( %counts, %direrrors ); - $debug and warn "Entering sub handle_dir; passed \$dir=$dir, \$suffix=$suffix"; + $logger->debug("Entering sub handle_dir; passed \$dir=$dir, \$suffix=$suffix"); if ( $suffix =~ m/zip/i ) { # If we were sent a zip file, process any included data/idlink.txt files my ( $file, $filename ); undef $cardnumber; - $debug and warn "Passed a zip file."; + $logger->debug("Passed a zip file."); opendir DIR, $dir; while ( my $filename = readdir DIR ) { $file = "$dir/$filename" if ( $filename =~ m/datalink\.txt/i || $filename =~ m/idlink\.txt/i ); } - unless ( open( FILE, $file ) ) { + my $fh; + unless ( open( $fh, '<', $file ) ) { warn "Opening $dir/$file failed!"; $direrrors{'OPNLINK'} = $file; # This error is fatal to the import of this directory contents @@ -192,12 +221,12 @@ sub handle_dir { return \%direrrors; } - while ( my $line = ) { - $debug and warn "Reading contents of $file"; + while ( my $line = <$fh> ) { + $logger->debug("Reading contents of $file"); chomp $line; - $debug and warn "Examining line: $line"; + $logger->debug("Examining line: $line"); my $delim = ( $line =~ /\t/ ) ? "\t" : ( $line =~ /,/ ) ? "," : ""; - $debug and warn "Delimeter is \'$delim\'"; + $logger->debug("Delimeter is \'$delim\'"); unless ( $delim eq "," || $delim eq "\t" ) { warn "Unrecognized or missing field delimeter. Please verify that you are using either a ',' or a 'tab'"; $direrrors{'DELERR'} = 1; @@ -208,11 +237,11 @@ sub handle_dir { ( $cardnumber, $filename ) = split $delim, $line; $cardnumber =~ s/[\"\r\n]//g; # remove offensive characters $filename =~ s/[\"\r\n\s]//g; - $debug and warn "Cardnumber: $cardnumber Filename: $filename"; + $logger->debug("Cardnumber: $cardnumber Filename: $filename"); $source = "$dir/$filename"; %counts = handle_file( $cardnumber, $source, $template, %counts ); } - close FILE; + close $fh; closedir DIR; } else { @@ -224,7 +253,7 @@ sub handle_dir { sub handle_file { my ( $cardnumber, $source, $template, %count ) = @_; - $debug and warn "Entering sub handle_file; passed \$cardnumber=$cardnumber, \$source=$source"; + $logger->debug("Entering sub handle_file; passed \$cardnumber=$cardnumber, \$source=$source"); $count{filenames} = () if !$count{filenames}; $count{source} = $source if !$count{source}; $count{count} = 0 unless exists $count{count}; @@ -238,7 +267,7 @@ sub handle_file { } if ( $cardnumber && $source ) { # Now process any imagefiles - $debug and warn "Source: $source"; + $logger->debug("Source: $source"); my $size = ( stat($source) )[7]; if ( $size > 550000 ) { # This check is necessary even with image resizing to avoid possible security/performance issues... @@ -255,9 +284,9 @@ sub handle_file { return %count; } my ( $srcimage, $image ); - if ( open( IMG, "$source" ) ) { - $srcimage = GD::Image->new(*IMG); - close(IMG); + if ( open( my $fh, '<', $source ) ) { + $srcimage = GD::Image->new($fh); + close($fh); if ( defined $srcimage ) { my $imgfile; my $mimetype = 'image/png'; @@ -265,10 +294,10 @@ sub handle_file { # we will convert all to PNG which is lossless... # Check the pixel size of the image we are about to import... my ( $width, $height ) = $srcimage->getBounds(); - $debug and warn "$filename is $width pix X $height pix."; + $logger->debug("$filename is $width pix X $height pix."); if ( $width > 200 || $height > 300 ) { # MAX pixel dims are 200 X 300... - $debug and warn "$filename exceeds the maximum pixel dimensions of 200 X 300. Resizing..."; + $logger->debug("$filename exceeds the maximum pixel dimensions of 200 X 300. Resizing..."); # Percent we will reduce the image dimensions by... my $percent_reduce; if ( $width > 200 ) { @@ -283,58 +312,70 @@ sub handle_file { sprintf( "%.0f", ( $width * $percent_reduce ) ); my $height_reduce = sprintf( "%.0f", ( $height * $percent_reduce ) ); - $debug - and warn "Reducing $filename by " + $logger->debug("Reducing $filename by " . ( $percent_reduce * 100 ) - . "\% or to $width_reduce pix X $height_reduce pix"; + . "\% or to $width_reduce pix X $height_reduce pix"); #'1' creates true color image... $image = GD::Image->new( $width_reduce, $height_reduce, 1 ); $image->copyResampled( $srcimage, 0, 0, 0, 0, $width_reduce, $height_reduce, $width, $height ); $imgfile = $image->png(); - $debug - and warn "$filename is " + $logger->debug("$filename is " . length($imgfile) - . " bytes after resizing."; + . " bytes after resizing."); undef $image; undef $srcimage; # This object can get big... } else { $image = $srcimage; $imgfile = $image->png(); - $debug - and warn "$filename is " . length($imgfile) . " bytes."; + $logger->debug("$filename is " . length($imgfile) . " bytes."); undef $image; undef $srcimage; # This object can get big... } - $debug and warn "Image is of mimetype $mimetype"; - my $dberror; + $logger->debug("Image is of mimetype $mimetype"); if ($mimetype) { - $dberror = - PutPatronImage( $cardnumber, $mimetype, $imgfile ); - } - if ( !$dberror && $mimetype ) { - # Errors from here on are fatal only to the import of a particular image - #so don't bail, just note the error and keep going - $count{count}++; - push @{ $count{filenames} }, - { source => $filename, cardnumber => $cardnumber }; - } - elsif ($dberror) { - warn "Database returned error: $dberror"; - ( $dberror =~ /patronimage_fk1/ ) - ? $filerrors{'IMGEXISTS'} = 1 - : $filerrors{'DBERR'} = 1; - push my @filerrors, \%filerrors; - push @{ $count{filenames} }, - { - filerrors => \@filerrors, - source => $filename, - cardnumber => $cardnumber - }; - $template->param( ERRORS => 1 ); + my $patron = Koha::Patrons->find({ cardnumber => $cardnumber }); + if ( $patron ) { + my $image = $patron->image; + $image ||= Koha::Patron::Image->new({ borrowernumber => $patron->borrowernumber }); + $image->set({ + mimetype => $mimetype, + imagefile => $imgfile, + }); + eval { $image->store }; + if ( $@ ) { + # Errors from here on are fatal only to the import of a particular image + #so don't bail, just note the error and keep going + warn "Database returned error: $@"; + $filerrors{'DBERR'} = 1; + push my @filerrors, \%filerrors; + push @{ $count{filenames} }, + { + filerrors => \@filerrors, + source => $filename, + cardnumber => $cardnumber + }; + $template->param( ERRORS => 1 ); + } else { + $count{count}++; + push @{ $count{filenames} }, + { source => $filename, cardnumber => $cardnumber }; + } + } else { + warn "Patron with the cardnumber '$cardnumber' does not exist"; + $filerrors{'CARDNUMBER_DOES_NOT_EXIST'} = 1; + push my @filerrors, \%filerrors; + push @{ $count{filenames} }, + { + filerrors => \@filerrors, + source => $filename, + cardnumber => $cardnumber + }; + $template->param( ERRORS => 1 ); + } } - elsif ( !$mimetype ) { + else { warn "Unable to determine mime type of $filename. Please verify mimetype."; $filerrors{'MIMERR'} = 1; push my @filerrors, \%filerrors;