Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Lost Backs\ash

by eoin (Monk)
on Aug 14, 2003 at 10:54 UTC ( [id://283824]=perlquestion: print w/replies, xml ) Need Help??

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

Hey all,

I've recently had quite a few problems with this cgi upload script, as you can see here and finnaly when i'm sure I have it figured I get one last stumpper!!

I've looked into the docs for CGI.pm but I couldn't find a solution to my problem. After a bit of pondering i'v discovered that the script will work(or a least I hope so) from a *nix run because they use / as there directory structure dividers but windows use \ and the way my script works it seems to interpolate the whole file name string taken in by the %pics.

So what should be " C:\WINDOWS\Profiles\eoin\My Documents\images\border.jpg" Acctualy becomes "C:WINDOWSProfilesoinMy Documentsimageorder.jpg"

Before I get a chance to stip the filepath from the filename. And obviously the stripping process won't work anymore because there is nothing to strip from. (I.e no \). Is there anyway to fix this without changing alot of the script.


Thanks for any help in advance.

The codes inside
#!/usr/bin/perl -w use strict; use warnings; use diagnostics; use CGI; my %pics; my @pic_filehandles; my @filelist; my $key; my @files; my $upload_dir; my $q = CGI->new; my $user = $q->param("user"); my $album = $q->param("T1"); unless ( -d "./albums/$album" ) { mkdir( "./albums/$album", 0775 ); $upload_dir = "./albums/$album"; } { $pics{"pic$_"} = $q->param("photo$_") for 0..13; @pic_filehandles = map { $q->upload("photo$_") } '',0..13; } strip_filename(); sub strip_filename{ my @allkeys = sort(keys(%pics)); foreach $key (@allkeys) { $pics{$key} =~ s/.*[\/\\](.*)/$1/; } } my $cntr = 0; @files = sort(keys(%pics)); foreach $key (@files) { open IMAGE, ">$upload_dir/$pics{$key}"; binmode IMAGE; while (<$pic_filehandles[$cntr]>) { print IMAGE; } close IMAGE; $cntr += 1; } print $q->header ( ); print <<END_HTML; <HTML> <HEAD> <TITLE>Thanks!</TITLE> </HEAD> <META HTTP-EQUIV="refresh" CONTENT="05;URL=http://eoinmurphy00.netfirm +s.com/cgi-bin/main.cgi?status=home&user=$user"> <title>Please Wait</title><head>Thank you for uploading your Photos.<b +ody>Please Wait<br>You will be redirected to the main page in 2 secon +ds.<br>Thank You $user</body> </HTML> END_HTML

All the Best, Eoin...

If everything seems to be going well, you obviously don't know what the hell is going on.

Replies are listed 'Best First'.
Re: Lost Backs\ash
by diotalevi (Canon) on Aug 14, 2003 at 11:43 UTC

    If you want to have a literal backslash in a string then you have to escape it. You wrote " C:\WINDOWS\Profiles\eoin\My Documents\images\border.jpg" but really you have to write that as " C:\\WINDOWS\\Profiles\\eoin\\My Documents\\images\\border.jpg".

    Added: Oh I see. You're using the filename all wrong. You have to accept that the filename as given by the browser isn't going to be used locally since you can't really trust it to be sane. Consider this - depending on the browser the filename may contain backslashes, slashes or colons or perhaps other odd things. Those are all OS dependant characters and you can't really trust them all too much. Here's an alternate implementation.

    A short list of changes:

    • Removed a security hole
    • Used taint mode (read perlsec if you haven't already)
    • Removed a bug - you didn't fetch the $pics{'pic'} entry before.
    • Switched to the standard File::Spec
    • Used CGI to generate the HTML since your HTML was invalid
    • Replaced './albums' with a configuration variable
    • Made an example of localizing a filehandle before using it which is always important in larger scripts
    • Made an example of not using the implict $_ stomping behaviour of while(<..>) - again something to think about in larger scripts
    • Added error detection on system calls (open,print,close)
    • Lastly, because I was doing the work for you I made the formatting look nice to me.
    ##!/usr/bin/perl -wT use strict; use warnings; use diagnostics; use File::Spec::Functions; use CGI qw(:standard); our $ALBUM_DIR = "albums"; my $user = param("user"); my ($album) = param("T1") =~ /([\w ]+)/; # Untaint the album dir name my $albumdir = catdir( $ALBUMDIR, $album ); unless ( -d $albumdir ) { mkdir $albumdir, 0775; } my @pics; for ( '', 0 .. 13 ) { push @pics, { idx => $_, name => (param("photo$_") =~ /.+([\w. ]+)/)[0], fh => upload("photo$_") }; } foreach my $pic (@pics) { my $name = $pic->{'name'}; my $fh = $pic->{'fh'}; my $filenm = catfile( $albumdir, "pic$idx" ); local *IMAGE; open IMAGE, ">", $filenm or die "Couldn't open $filenm for writing: $!"; binmode IMAGE; while (my $line = <$fh>) { print IMAGE $line or die "Couldn't write to $filenm: $!"; } close IMAGE or die "Couldn't close $filename while writing: $!"; } print header, start_html( -title => 'Please Wait', -meta => { "HTTP-EQUIV" => "refresh", CONTENT => "05;URL=http://eoinmurphy00.netfirms.com/cgi- +bin/main.cgi?status=home&user=$user" }, ), p('Please Wait'), p('You will be redirected to the main page in two seconds.'), p("Thank you $user"), end_html;
      I understand that, but this is for input form a file upload web form so the user will be using a browse button to choose a file and then that filename and path will appear in the textbox and then you click submit. So I have no control over what is sent by the form but only what the script revcieves and uses.
      Its a real head tangler.
      All the Best, Eoin...

      If everything seems to be going well, you obviously don't know what the hell is going on.

Re: Lost Backs\ash
by bm (Hermit) on Aug 14, 2003 at 11:11 UTC
    Perhaps File::Basename (part of core Perl) will be better than your strip_filename routine. It is OS aware.
    --
    bm
Re: Lost Backs\ash
by cfreak (Chaplain) on Aug 14, 2003 at 13:36 UTC

    Honestly have you tested this? I've done countless upload scripts and the only thing the browser is supposed to send is the filename itself, so if you have

    C:\Windows\My Documents\foo.jpg
    The browser should only send back 'foo.jpg'. Now of course there are exceptions, namely that evil browser made in Redmond IE 5 I believe sends the entire thing, but the '\' marks get sent with it. I get around that by doing this:
    my $filename = $cgi->param('uploadedfile'); if($filename =~ /\\/) { my @tmp = split(/\\/,$filename); $filename = pop(@tmp); }
    In your case you could probably run that bit of code in a loop to fix all your filenames, should they have that problem.

    Lobster Aliens Are attacking the world!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://283824]
Approved by gjb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2024-04-19 23:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found