MonkPaul has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

Further to my post eariler today on files and server interaction... i have a new problem, i cannot open files for reading or writing.

I know the code worked in the past from use with command line, but i have since tried to adapt it for use with a web page upload.

I cant see why it would work.

some variables declared before the method calls and the correct syntax + for a CGI script. ###################################################################### +######### sub get_Input() { $html = new CGI; # create a new instance of CGI to upload +file $blastFile = $html->param('blast_Upload'); # upload file $refFile = $html->param('ref_Upload'); # upload file $blastSeq = param("blast_Seq"); chomp($refFile); @dir = split(/\\/, $refFile); pop(@dir); $pathName = join('\\', @dir); print("<BR>$pathName is the location files will be saved to<BR>"); print("<BR>$blastFile<BR>"); print("<BR>$refFile<BR>"); } ###################################################################### +######### sub get_Results() { #my $referenceFile; #my $blastFile; #if using this WITHOUT an reference file as input, cmdline must be as +follows # --blastresult result.txt --reffile file.txt (even if it's an empty f +ile) #GetOptions( "blastresult=s" => \$blastFile, "reffile=s" => \$refFile) +; my $ref_File = "<" . $refFile; my $blast_File = "<" . $blastFile; print("<BR>$blast_File<BR>"); print("<BR>$ref_File<BR>"); ## open file handles.############## PROBLEM HERE ########## open( BLAST_FILE, $blast_File ) || die "$!"; open( REF_FILE, $ref_File ) || die "$!"; print("Blast File Opened<BR>"); print("Reference File Opened<BR>"); ## output files - open them my $newRefFile = "$pathName\\newRefFile.txt"; my $newBlastFile = "$pathName\\newBlastFile.txt"; open( NEW_ACC, ">$newRefFile" ) || die "$!"; open( NEW_ALIGN, ">$newBlastFile") || die "$!"; print("New files created<BR>"); ## put list of reference accessions into a structure so we can parse i +t... my $refList = {}; # reference to empty hash while (<REF_FILE>) { chomp; # removes newline charac +ter $refList->{$_} = ""; # $_ is whatever line is currently open, t +hus creating a hash with key = accession, value = " "(.: defined) } #PARSE BLAST RESULT HERE.... #read results file one line at a time my @resultLine = <BLAST_FILE>; my $alignment = {}; # reference to an empty hash my @subjects = []; # reference to empty array my $current_subject = "front_matter"; $alignment->{$current_subject} = ""; #so I produce a hash with key = >gi line of report and value = all lin +es after until next >gi for (my $i = 0 ; $i<scalar @resultLine; $i++) { if ($resultLine[$i] =~ /^>/) { $current_subject = $resultLine[ $i ]; chomp ($current_subject); push (@subjects, $current_subject); $alignment->{$current_subject} = ""; #$alignment->{$current +_subject} means give value of $alignment when $current_subject is the + key } $alignment->{$current_subject} = $alignment->{$current_subject} . +$resultLine[ $i ]; } my @elements; foreach my $z (@subjects) { chomp $z; print "$z\n"; @elements = split('\|', $z); if ( ! defined $elements[ 3 ] ) { print "<BR>Parsing Error<BR>"; print "<BR>Line $z<BR>"; } if (defined $elements[ 3 ] && defined $refList->{$elements[3]}) { print "<Br>Match<BR>"; } else { print "<BR>No match<BR>"; print NEW_ALIGN $alignment->{$z} . "<BR>"; print NEW_ACC $elements[3]."<BR>"; print $alignment->{$z} . "<BR>"; print $elements[3]."<BR>"; } } #close files close REF_FILE; close BLAST_FILE; close NEW_ALIGN; close NEW_ACC; }

I know the code is working upto the file opening as it prints the details on the screen, but when it gets to the BLAST_FILE open statement it produces an error saying "Content-type: text/html Software error: No such file or directory at BlastTool.cgi line 77. For help, please send mail to the webmaster (root@localhost), giving this error message and the time and date of the error."

Any ideas - im currently using (fatalstobrowser) and other error checking properties but no idea why.

Cheers, MonkPaul.

UPDATE:: I have changed the \n to \\n and the =~ to =

Janitored by holli - added readmore tags

Replies are listed 'Best First'.
Re: Cannot open files using CGI
by injunjoel (Priest) on May 28, 2005 at 20:54 UTC
    Greetings all,
    I must admit I have only briefly looked over your posted code yet there is one thing I would like to mention regarding file uploads with CGI. You must designate your html form as such
    <form enctype="multipart/form-data">
    this prepares the browser for possible incoming binary data, aka a file upload. Without it you will get the name of the file but its contents will not get passed to your script. The documentation from CGI regarding file uploads can be found here. Once you have that follow the documentation on how to handle the incoming file and you should be golden.

    -InjunJoel
    "I do not feel obliged to believe that the same God who endowed us with sense, reason and intellect has intended us to forego their use." -Galileo
      I can understand you point, some people miss the basics but i double checked my HTML syntax and its got all the necessaries.

      Thanks anway though.

Re: Cannot open files using CGI
by thundergnat (Deacon) on May 28, 2005 at 21:16 UTC

    I would suspect that these two lines;

    my $ref_File =~ "<" . $refFile; my $blast_File =~ "<" . $blastFile;

    really should be:

    my $ref_File = "<" . $refFile; my $blast_File = "<" . $blastFile;
Re: Cannot open files using CGI
by graff (Chancellor) on May 29, 2005 at 02:34 UTC
    In addition to what others have said, these two lines look like a problem:
    my $newRefFile = "$pathName\newRefFile.txt"; my $newBlastFile = "$pathName\newBlastFile.txt";
    Those backslashes won't show up the way you expect unless you double them -- all they're doing here is inserting a newline in the strings. If $pathName is being defined the same way, the problem is compounded. I'm doubtful that this code works from the command line.

    You might as well just use a plain old forward slash for separating directory names, because perl will know what you mean by that and do the Right Thing. (Or you could use the appropriate File:: module(s) to construct path names in an OS-neutral manner.)

      Yes, well spotted. I had not seen that. Doh!

      With regards to the file permissions do these have to be changed when the file is uploaded to the server using e.g. O_RDRW and chmod 755.

      The server is a whack biolinux server if that helps (dont know of it matters much if its the file permissions though).

      Cheers
      MonkPaul.

        If the server that this cgi script is running on is a linux box, you damn well better not use backslashes at all in the path names for input or output files. As for setting permissions, the only thing you need to worry about is that the "user" account that is the web server has read+execute permission at each directory layer above the directory where file will be stored; and it must have read+write+execute on the storage directory.

        If the storage directory is owned by the web server user account, its permission can be 755; if it's owned by some other user, but has group ownership that matches the web server's group, then it can be 775. As for permissions on the files that are created, that's up to you.

      linux may allow it, but having "\n" in filenames is a bad idea
Re: Cannot open files using CGI
by thcsoft (Monk) on May 29, 2005 at 01:44 UTC
    your problem is most probably none of perl, but has to to with the file permissions on your server. for instance: on a debian box the webserver is called www-data, group www-data. if you want your cgi-scripts to open files, you should take care that they belong to the server.

    language is a virus from outer space.

      That being said, you also might run into "Security Context" problems (see chcon). It had me puzzled and cursing for quite some time (on a remote CentOS machine).

      Very tricky, for I never use "ls --scontext" to check permissions...

      --
      b10m

      All code is usually tested, but rarely trusted.