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

YaBB is a BBS for those who don't use it. There aren't many CGI ones around, most of them are PHP and I'd never use that on my server.

I am trying to hack this to allow more than one file attachment. The code is pretty self explanatory and I appologize if it's a little long.

My question is this: does anyone know of a simple way to loop over all of this data? It's calling $FORM{'file'} as the file, so I'd be creating $FORM{'file1'}, file2, file3, etc.

I'd need to loop over all file# parts of the hash. Any suggestions on the best method to make this 1-attachment process into multiple attachments?

if ($FORM{'file'} ne "") { $file = $FORM{'file'}; $OS = $^O; # operating system name if ($OS =~ /darwin/i) { $isUNIX = 1; } elsif ($OS =~ /win/i) { $isWIN = 1; } else { $isUNIX = 1; } $mylimit = 1024 * $limit; $mydirlimit = 1024 * $dirlimit; $fixfile = $file; $fixfile =~ s/.+\\([^\\]+)$|.+\/([^\/]+)$/$1/; $fixfile =~ s/[\(\)\$#%+,\/:?"<>'\*\;|@^!]//g; # edit in be +tween [ ] to include characters you dont want to allow in filenames ( +dont put a . there or you wont be able to get any file extensions). $fixfile =~ s/ /_/g; # replaces s +paces in filenames with a "_" character. $fixfile =~ s/&//g; # replaces a +mpersands with nothing. $fixfile =~ s/\+//g; # replaces + + with nothing $fixfile =~ s~[^/\\0-9A-Za-z#%+\,\-\ \.\:@^_]~~g; # Remove all + inappropriate characters. # replace . with _ in the filename except for the extension $fixname = $fixfile; $fixname =~ s/(\S+)(\.\S+\Z)/$1/gi; $fixext = $2; $fixext =~ s/(pl|cgi|php)/_$1/gi; $fixname =~ s/\./\_/g; $fixfile = qq~$fixname$fixext~; if ($overwrite == 2 && (-e "$uploaddir/$fixfile")) { &fatal_er +ror("$fatxt{'8'}"); } if (!$overwrite) { $fixfile = check_existence($uploaddir, $fixfile); } if ($checkext == 0) { $match = 1; } else { foreach $ext (@ext) { chomp($ext); if (grep /$ext$/i, $fixfile) { $match = 1; last; } } } if ($match) { if ($allowattach == 1 && (($allowguestattach == 0 && $user +name ne 'Guest') || $allowguestattach == 1)) { $upload_okay = 1; } } else { &Preview("<br /><br />$fatxt{'20'} @ext ($fixfile)") } if ($mydirlimit > 0) { &dirstats; } $filesize = $ENV{'CONTENT_LENGTH'} - $postsize; $filesizekb = int($filesize / 1024); if ($filesize > $mylimit && $mylimit != 0) { $filesizediff = $filesizekb - $limit; if ($filesizediff == 1) { $sizevar = "kilobyte"; } else { $sizevar = "kilobytes"; } &Preview("<br /><br />$fatxt{'21'} $filesizediff $sizevar +$fatxt{'21b'}") } elsif ($filesize > $spaceleft && $mydirlimit != 0) { $filesizediff = $filesizekb - $kbspaceleft; if ($filesizediff == 1) { $sizevar = "kilobyte"; } else { $sizevar = "kilobytes"; } &Preview("<br /><br />$fatxt{'22'} $filesizediff $sizevar +$fatxt{'22b'}"); } if ($upload_okay == 1) { # create a new file on the server using the formatted ( ne +w instance ) filename if (fopen(NEWFILE, ">$uploaddir/$fixfile")) { if ($isWIN) { binmode NEWFILE; } # start reading users HD. while (<$filename>) { # print to the new file on the server print NEWFILE; } # close the new file on the server and we're done fclose(NEWFILE); } else { # return the server's error message if the new file co +uld not be created &fatal_error("$fatxt{'60'} $uploaddir"); } } # check if file has actually been uploaded, by checking the fi +le has a size if (-s "$uploaddir/$fixfile") { $upload_ok = 1; } else { # delete the file as it has no content unlink("$uploaddir/$fixfile"); &fatal_error("$fatxt{'59'} $fixfile"); } if ($fixfile =~ /(jpg|gif|png|jpeg)$/i) { $okatt = 1; if ($fixfile =~ /(gif)$/i) { fopen(ATTFILE, "$uploaddir/$fixfile"); read(ATTFILE, $header, 10); ($giftest, undef, undef, undef, undef, undef) = unpack +("a3a3C4", $header); fclose(ATTFILE); if ($giftest ne "GIF") { $okatt = 0; } } fopen(ATTFILE, "$uploaddir/$fixfile"); while ( read(ATTFILE, $buffer, 1024) ) { if ($buffer =~ /\<html/ig || $buffer =~ /\<script/ig) +{ $okatt = 0; last; } } fclose(ATTFILE); if(!$okatt) { # delete the file as it contains illegal code unlink("$uploaddir/$fixfile"); &fatal_error("$fatxt{'59'} $fixfile"); } } &clear_temp; }

Replies are listed 'Best First'.
Re: YaBB mod patch
by chromatic (Archbishop) on Feb 11, 2006 at 22:11 UTC
    Any suggestions on the best method to make this 1-attachment process into multiple attachments?

    The best way is probably to refactor all of the (broken) custom form-parsing code to use a secure, working parser such as that in CGI or CGI::Simple. Honestly, I'm not sure this code is worth it. It has problems.

    The "easiest" way to do this is probably to loop over all of the potential hash keys in %FORM you expect to contain uploaded files, setting $FORM{file} to each in turn, and calling this piece of code as a subroutine.

      Oh I know this code kind of sucks, to say the least, but it is the best free CGI one I found. Server doesn't run ASP or CFM, and PHP itself is just crap. I'm thinking about converting pieces of it to using CGI though to make addons like this a little less problematic.
        i'm working on a perl bb that's a big improvement on the one's out there currently, so if you keep in touch i can keep you updated. it'll be free of course, but it's moving slowly right now.
        meh.
      To say that YABB's code "has problems" is an understatement along the lines of saying that elephants may be too large to fit in your pocket. Just don't use it. The code is crap. I have ranted about this before here.