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

Good Evening,

I'm brand new to the site and perl so bear with me.

I have a cgi/perl script which works fine except I wish to check the size of a directory as a client adds files and issus a warning. The problem is the result always seems to give me an erroneous value. I have been dealing with a person at the Experts-Exchange and hs basically has given up after a week and suggested I ask you.

Rather than post all that has been done he suggested pointing to their response page.

This has the history of the incident. My host is running linux, and Apache server 1.3.27(unix) and perl 5.006001. The code is listed below.

#!/usr/bin/perl -w use CGI; @valid = ('theartistloft.com'); $maxfoldersize = "200000"; $query = new CGI; $comments = $query->param("Comments"); $filename = $query->param("file_name"); $fsize = -s $filename; $email_address = $query->param("email_address"); #! try to create directory $upload_dir = "/home/bsexton/public_html/NEWClients/$email_address"; unless (-d "$upload_dir"){ mkdir ("$upload_dir", 0777); chmod(0777, "$upload_dir"); } #! end of create directory $filename =~ s/.*[\/\\](.*)/$1/; $upload_filehandle = $query->upload("file_name"); open UPLOADFILE, ">$upload_dir/$filename"; while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE; $filename1 = $query->param("file_name1"); $fsize1 = -s $filename1; $filename1 =~ s/.*[\/\\](.*)/$1/; #! End of Folder Check $upload_filehandle = $query->upload("file_name1"); open UPLOADFILE, ">$upload_dir/$filename1"; while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE; $filename2 = $query->param("file_name2"); $fsize2 = -s $filename2; $filename2 =~ s/.*[\/\\](.*)/$1/; $upload_filehandle = $query->upload("file_name2"); open UPLOADFILE, ">$upload_dir/$filename2"; while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE; $filename3 = $query->param("file_name3"); $fsize3 = -s $filename3; $filename3 =~ s/.*[\/\\](.*)/$1/; $upload_filehandle = $query->upload("file_name3"); open UPLOADFILE, ">$upload_dir/$filename3"; while ( <$upload_filehandle> ) { print UPLOADFILE; } close UPLOADFILE; $todays_upload = $fsize + $fsize1 + $fsize2 + $fsize3; print $query->header ( ); #! Check Folder Size use File::Find; $File::Find::dir = $upload_dir; my $total_size = 0; find(sub { $total_size += -s }, @ARGV ? @ARGV : '.'); if ($total_size > $maxfoldersize) { print"You have exceded your limit of $maxfoldersize KB for the directo +ry $email_address \n"; } #! End of Folder Check $from = 'sales@theartistloft.com'; $subject = 'New Artist Loft Signup'; open(MAIL, "|/usr/sbin/sendmail -t"); print MAIL "To: $email_address\n"; print MAIL "From: $from\n"; print MAIL "Subject: $subject\n\n"; print MAIL "Dear Client:\n\n"; print MAIL "Thank you for signing up for The Artist Loft.\n\n"; print MAIL "This message is to confirm your transmission of $filename, + $filename1, $filename2, $filename3 from your PC today.\n\n"; print MAIL "Your Comments: $comments\n\n"; print MAIL "For future upload modifications and use of the chatroom, p +lease use the following information.\n\n"; print MAIL "Username = The Artist Loft\n"; print MAIL "Password = demo\n\n"; print MAIL "REMEMBER: username and password are case sensitive\n\n"; print MAIL "Thank you.\n"; print MAIL "Sales Department\n"; print MAIL "The Artist Loft\n"; close(MAIL); $to = 'newclient@theartistloft.com'; $from = 'sales@theartistloft.com'; $subject = 'A New Artist Loft Cleint'; open(MAIL, "|/usr/sbin/sendmail -t"); print MAIL "To: $to\n"; print MAIL "From: $from\n"; print MAIL "Subject: $subject\n\n"; print MAIL "Dear Sales Department:\n\n"; print MAIL "This message is to confirm transmission of $filename($fsiz +e), $filename1($fsize1), $filename2($fsize2), $filename3($fsize3) fro +m our new client $email_address today. Todays total was $todays_uploa +d bytes.\n\n"; print MAIL "Client Comments: $comments\n\n"; print MAIL "The Artist Loft\n\n"; print MAIL "Size of Directory $email_address = $total_size\n"; close(MAIL); print <<END_HTML; <HTML> <HEAD> <TITLE>Thanks!</TITLE> </HEAD> <BODY> <P align="center">&nbsp;</P> <P align="center"><b><font size="5">Thanks for uploading your file!</f +ont></b></P> <P align="center"><b><font size="4">Your email address: $email_address +</font></b></P> <P align="center"><b><font size="4">Your file(s): $filename, $filename +1, $filename2, $filename3</font></b></P> </BODY> </HTML> END_HTML

Edited: ~Thu Nov 21 23:15:49 2002 (GMT) by footpad: Added <HTML> (and <READMORE>) formatting tags. Also retitled node and replies (was "Stumped Newbie") to aid future searching, per Consideration

Replies are listed 'Best First'.
Re:Stumped with File::Find and -s
by tadman (Prior) on Nov 21, 2002 at 22:30 UTC
    From the looks of things, you'll want to familiarise yourself with some of the modules bundled with Perl that can make your life a lot easier. For example, if you need to make a directory, you can use File::Path:
    use File::Path; # ... unless (-d $upload_dir) { mkpath($upload_dir); }
    You will note, though, that this is pretty bold, taking a parameter in from the CGI input and making a directory based on that name. You should take great care to make sure that this directory name is valid, and, for example, doesn't contain values like "../../../.w4r3z/"

    Instead of cranking open something like Sendmail directly, try using Mail::Sender or Mail::Mailer which give you a simpler interface.

    Most important, of course, is to use strict which is not optional if you want to do things properly. Yes, you have to declare your variables, each and every one of them, but this shouldn't be considered bad.

    If you could post the error you're getting, that might help with diagnosis.
      Thanks for the advice. Like I said I'm brand new with perl and the script started out as a simpler free script that I started trying to adjust to meet my needs.
Re: Stumped with File::Find and -s
by dws (Chancellor) on Nov 21, 2002 at 22:25 UTC
    What, exactly, do you expect   $fsize = -s $filename; to do if $filename doesn't exist in the same directory that holds the script? You're doing this before you've created "$upload_dir/$filename". Is that what you intend to do?

      The $fsize = -s $filename is getting the size of the file they are trying to upload so I'll eventually be able to check that the limit is not reached, since 4 files are uploadable at a time from the input form.
Re: Stumped with File::Find and -s
by BrowserUk (Patriarch) on Nov 21, 2002 at 22:25 UTC

    Could you give us more indication of what you mean by

    the result always seems to give me an erroneous value
    ?

    I followed the link (please read perl monks site FAQ, and What shortcuts can I use for linking to other information?) you gave and all I found there was what I take to be an earlier version of the same code, but no indication of what the specific problem is with your latest version?


    Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
    Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
    Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
    Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.

      By erroneous answer, I mean I always get a value of around 55,300 + or - a little, even thought the directory may only have 4 files totaling 1800 bytes of less.

        The problem, as identified by dws and tadman is that the use of File::Find is completely wrong.

        The line $File::Find::dir = $upload_dir; is having no effect whatsoever and is not intended for use this way.

        When you call find(), you are supplying the base of the subtree that the routine will search. As @ARGV will normally have no contents at all, or at least none that would be useful to you for this purpose, the @ARGV ? @ARGV : '.' almost certainly means that you are searching the subtree starting at '.', which is whatever place in the file system your CGI script is being invoked from.

        Your ../cgi-bin/ directory perhaps? This would explain why you are getting the same numbers back each time. To correct this, you need to supply the upload directory directly to the find() function.

        use File::Find; my $total_size = 0; find(sub { $total_size += -s }, $upload_dir );

        In the short-term, that may well cure your problem. In the long term, you really should read up on the use of taint, and starting checking that you have at least got something in the $email_address variable before blindly appending it to your upload path.

        You should seriously consider reading ovid's CGI programming course and pay special attention to lesson three unless you want your site to be overrun by the worlds script kiddies, because currently you are very vulnerable.


        Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
        Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
        Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
        Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.