1

This Perl script uploads an image to server and then saves: - a gallery image that fits in 900x900 px - a square gallery thumbnail 140x140 px - adds a line in a js file with the image and thumbnail names

The problem is, that the script sometimes works, sometimes - not. It works fine in one or two of every ten attempts. When it doesn't work, it usually returns "Internal Server Error" and doesn't create two files, nor adds a line in js. But in some cases it creates the both jpg files and doesn't add a line in js (again returning "Internal Server Error"). Very strange behavior - I've tried various changes with no result. What I do wrong?

#!/usr/bin/perl -w
##
##

use strict;
use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;
use Image::Magick;

$CGI::POST_MAX = 1024 * 70000;
my $safe_filename_characters = "a-zA-Z0-9_.-";
my $pic_upload_dir="../data/photos/gallery";
my $lst_upload_dir="../data";
my $lst_file=$lst_upload_dir."/gallery.js";

my $query=new CGI;

my $PictureIndex=$query->param("Snd_AddPhoto_Idx");
my $photoname=$query->param("AddPhoto");

    #upload photo
    if ( !$photoname ) {  
        print "Content-Type: text/plain\n\n";
        print "\n\nThere was a problem uploading your photo (try a smaller size).\n";
        exit;
    }  

    my ( $phname, $phpath, $phextension ) = fileparse ($photoname, qr/\.[^.]*/);
    $photoname = $phname . $phextension;
    $photoname =~ tr/ /_/;
    $photoname =~ s/[^$safe_filename_characters]//g;

    if ( $photoname =~ /^([$safe_filename_characters]+)$/ ) {  
        $photoname = $1;
    }  
    else {  
        die "Filename contains invalid characters";
    }  

        # force correct filename for temporary file
        $photoname="tempphoto_zmm_gallery_".$PictureIndex.$phextension;

    my $upload_photohandle = $query->upload("AddPhoto");

    open ( UPLOADPHOTO, ">$pic_upload_dir/$photoname" ) or die "$!";
    binmode UPLOADPHOTO;
    while ( <$upload_photohandle> ) {  
        print UPLOADPHOTO;
    }  
    close UPLOADPHOTO;

    # resize photo
    my($photoimage) = Image::Magick->new;
    open(PHOTOIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
    $photoimage->Read(file=>\*PHOTOIMAGE);
    close(PHOTOIMAGE);

    $photoimage->Resize(geometry=>'900x900', blur=>0.8);
    $photoimage->Set(Quality=>'75%');

    # write ready photo as jpg
    my $readyphotoname="pic".$PictureIndex.".jpg";
    open(READYIMAGE, ">$pic_upload_dir/$readyphotoname") or die "Unable to write ready image file!\n";
    $photoimage->Write(file=>\*READYIMAGE, filename=>$readyphotoname);
    close(READYIMAGE);
    system("chmod 777 $pic_upload_dir/$readyphotoname");

    # resize thumbnail
    my($thumbimage) = Image::Magick->new;
    open(THUMBIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
    $thumbimage->Read(file=>\*THUMBIMAGE);
    close(THUMBIMAGE);

    $thumbimage->Resize(geometry=>'140x140^', blur=>0.8);
    $thumbimage->Set(gravity=>'Center');
    $thumbimage->Crop(geometry=>'140x140+0+0');
    $thumbimage->Set(Quality=>'30%');

    # write ready thumbnail as jpg
    my $readythumbname="tbn".$PictureIndex.".jpg";
    open(READYTHUMB, ">$pic_upload_dir/$readythumbname") or die "Unable to write ready image file!\n";
    $thumbimage->Write(file=>\*READYTHUMB, filename=>$readythumbname);
    close(READYTHUMB);
    system("chmod 777 $pic_upload_dir/$readythumbname");

    # delete temporary file
    my($temporary_file)=$pic_upload_dir."/".$photoname;
    unlink($temporary_file) == 0;


# add pic in js gallery list

    # prepare new pic record
    my $NewGalRecord="GalleryList.push(new Array(\"pic".$PictureIndex.".jpg\",\"tbn".$PictureIndex.".jpg\",\"\",\"\"));\n";

    # add to file
    open(JS,">>$lst_file") || die "Failed to open $lst_file\n";
    printf JS $NewGalRecord;
    close JS;
    system("chmod 777 $lst_file");

# print confirmation

...
...
...


exit;
byddles
  • 27
  • 1
  • 7
  • When uploading the 'big' image only and no thumbnail (without 'resize thumbnail' and 'write ready thumbnail as jpg' sections) the script works fine every time. – byddles Jan 26 '15 at 23:34
  • 1
    What reported in the server logs? – emcconville Jan 27 '15 at 00:18
  • @emcconville `code`admin_zmm_gallery_add.cgi: Useless use of numeric eq (==) in void context at /home/zmm/public_html/cgi-bin/admin_zmm_gallery_add.cgi line 108. `code`admin_zmm_gallery_add.cgi: Argument "75%" isn't numeric in subroutine entry at /home/zmm/public_html/cgi-bin/admin_zmm_gallery_add.cgi line 78, line 6399. `code`admin_zmm_gallery_add.cgi: Argument "30%" isn't numeric in subroutine entry at /home/zmm/public_html/cgi-bin/admin_zmm_gallery_add.cgi line 97, line 6399. `code`Premature end of script headers: admin_zmm_gallery_add.cgi – byddles Jan 27 '15 at 08:27
  • ... these are the lines: unlink($temporary_file) == 0; $photoimage->Set(Quality=>'75%'); $thumbimage->Set(Quality=>'30%'); I don't know what is fh0000135.jpg - nor the image I try to upload, nor the temp image, nor the saved image has such a name. – byddles Jan 27 '15 at 08:31
  • I commented the "Set Quality" lines and script starts to work with images 1-2-3MB in size. With images 5-6MB still the same error. In log: Premature end of script headers: admin_zmm_gallery_add.cgi – byddles Jan 27 '15 at 08:43

1 Answers1

0

I think I've solved the problem. Obviously there's no need to read the temp file twice. After saving the 'big' image, we can continue manipulate it and then save again as thumbnail. Double reading of the temp file apparently causes conflict. Something like 'Sharing violation' - just a shot in the dark. But now the script works fine. Separately, far removed the rows Set(Quality=>). I don't know whether they have anything to do with the problem, but this will be subject to future testing. Here are the changes:

    # resize photo
    my($photoimage) = Image::Magick->new;
    open(PHOTOIMAGE, "$pic_upload_dir/$photoname") or die "Unable to open temporary image file!\n";
    $photoimage->Read(file=>\*PHOTOIMAGE);
    close(PHOTOIMAGE);

    $photoimage->Resize(geometry=>'900x900', blur=>0.8);

    # write ready photo as jpg
    my $readyphotoname="pic".$PictureIndex.".jpg";
    open(READYIMAGE, ">$pic_upload_dir/$readyphotoname") or die "Unable to write ready image file!\n";
    $photoimage->Write(file=>\*READYIMAGE, filename=>$readyphotoname);
    close(READYIMAGE);
    system("chmod 777 $pic_upload_dir/$readyphotoname");

    # resize thumbnail
    $photoimage->Resize(geometry=>'140x140^', blur=>0.8);
    $photoimage->Set(gravity=>'Center');
    $photoimage->Crop(geometry=>'140x140+0+0');

    # write ready thumbnail as jpg
    my $readythumbname="tbn".$PictureIndex.".jpg";
    open(READYTHUMB, ">$pic_upload_dir/$readythumbname") or die "Unable to write ready image file!\n";
    $photoimage->Write(file=>\*READYTHUMB, filename=>$readythumbname);
    close(READYTHUMB);
    system("chmod 777 $pic_upload_dir/$readythumbname");

    # delete temporary file
    my($temporary_file)=$pic_upload_dir."/".$photoname;
    unlink($temporary_file) == 0;
byddles
  • 27
  • 1
  • 7