original code:
open (REFFILE,"$reffile") || print "Content-type: text/html\n\n Can't +Open $reffile(r): $!\n"; my(@LINES)=<REFFILE>; close(REFFILE); $SIZE=@LINES; open (REFFILE,">$reffile") || print "Content-type: text/html\n\n Can't + Open $reffile(r): $!\n"; print REFFILE "$date\| $ENV{'REMOTE_HOST'}\| $ENV{'HTTP_USER_AGENT'}\| +$FORM{'discnt'}\|$FORM{'shipcountry'}\|\n";
Step 1 - DO IT!
At the very least please do not use the 2 argument form of open. It ~might~ be safe if you have that variable under your control but maybe at some point you decide it would be a nice feature for the user to be able to specify the file name and then you're in trouble. Your application may be tricked into setting '$reffile' to '>file', '<file', '-|file' or any other 'interesting' file modes. Use the 3 argument form, explicitely state the file mode and stop worrying.Check the return value of print and close. Both may fail!my $htmlheader = "Content-type: text/html\n\n"; open (REFFILE, '<', $reffile) || print "$htmlheader Can't Open $reffil +e(r): $!\n"; [...] open (REFFILE, '>', $reffile) || print "$htmlheader Can't Open $reffil +e(r): $!\n";
close(REFFILE) || print "$htmlheader Can't close filehandle for $reffile(r): $!\n"; [...] print (REFFILE "$date\| $ENV{'REMOTE_HOST'}\| $ENV{'HTTP_USER_AGENT'}\ +|$FORM{'discnt'}\|$FORM{'shipcountry'}\|\n") || "$htmlheader Can't write to $reffile(r): $!\n";
Step 2 - Recommended
Use 'or' instead of '||'. Both are 'logical or', but 'or' has a very low precedence allowing you to remove the parenthesis:my $htmlheader = "Content-type: text/html\n\n"; open REFFILE, '<', $reffile or print "$htmlheader Can't Open $reffile(r): $!\n"; my(@LINES)=<REFFILE>; close REFFILE or print "$htmlheader Can't close filehandle for $reffile(r): $!\n"; $SIZE=@LINES; open REFFILE, '>', $reffile or print "$htmlheader Can't Open $reffile(r): $!\n"; print REFFILE "$date\| $ENV{'REMOTE_HOST'}\| $ENV{'HTTP_USER_AGENT'}\| +$FORM{'discnt'}\|$FORM{'shipcountry'}\|\n" or "$htmlheader Can't write to $reffile(r): $!\n";;
Step 3 - Suggested
Use lexical variables (e.g. $fh_read, $fh_write) as filehandles. This is a precaution against name conflicts. You may accidentally define/import a function with the same name as one of your filehandles. Have fun debugging that. Lexical filehandles are safe and easy to use. Do yourself a favour and use them.Additional suggestion: brace file handles '{fh}' when writing to them. It doesn't matter to perl, but it makes the difference between printing a variable and writing to a file handle more obvious.
my $htmlheader = "Content-type: text/html\n\n"; open my $fh_read, '<', $reffile or print "$htmlheader Can't Open $reffile(r): $!\n"; my(@LINES)=<$fh_read>; close $fh_read or print "$htmlheader Can't close filehandle for $reffile(r): $!\n"; $SIZE=@LINES; open $fh_write, '>', $reffile or print "$htmlheader Can't Open $reffile(r): $!\n"; print {$fh_write} "$date\| $ENV{'REMOTE_HOST'}\| $ENV{'HTTP_USER_AGENT +'}\|$FORM{'discnt'}\|$FORM{'shipcountry'}\|\n" or "$htmlheader Can't write to $reffile(r): $!\n";
more DO IT!
Since you are writing environment variables to your file you should definitely verify their content. At the very least $ENV{'HTTP_USER_AGENT'}, $FORM{'discnt'} and $FORM{'shipcountry'} must be seen as containing something dangerous unless proven otherwise. Simply trusting the user provided data is likely to lead to data corruption sooner or later.example scrubber for 'shipcountry'
my $shipcountry; # shipcountry may contain letters, digits, underscores, spaces and das +hes # and nothing else if ($FORM{'shipcountry'} =~ /^([\w -]+)$/) { $shipcountry = $1; } else { print "$htmlheader Invalid input for shipping country detected!\n"; } print {$fh_write} "$date\| $ENV{'REMOTE_HOST'}\| $ENV{'HTTP_USER_AGENT +'}\|$FORM{'discnt'}\|$shipcountry\|\n" or "$htmlheader Can't write to $reffile(r): $!\n";
In reply to Re: Variable being saved as a list?
by Monk::Thomas
in thread Variable being saved as a list?
by fiona
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |