File::Temp: opening the temp. file in "r+" mode? Also "man in the middle"

A

A. Farber

Hi,

I'm working at a CGI-script which would receive a 20 MB
big file via HTTP-upload, then change few bytes in it,
then calculate an MD5 hash over a region of that file
and save that value into the file as well.

At the moment I do the first task (change few bytes) like
this (the $flash is coming from the CGI.pm's filefield):

my ($fh, $filename) = tempfile(DIR => UPLOADDIR);

while (sysread $flash, $chunk, KEYSIZE) {
$both = $prev . $chunk;
if ($both =~ s/$SEARCH/$REPLACE/o) {
print $fh $both;
undef $prev;
} else {
print $fh $prev;
$prev = $chunk;
}
}
# don't forget to print the last line
print $fh $prev;

Now I need to calculate the MD5 value and store it
in the file. Is there a safe way to reuse the $fh ?
Maybe somehow by using:

open(FILEHANDLE, "<&=$fh")

? But how do I specify the mode above? I need "rb+"
so that I can store the MD5 hash into the temp.file.

Also do I really need the new temp.file or is there
a nice way to work with CGI.pm's temp files?

And also actually the whole task I'm trying to solve
is that the file is being sent by TCP-connection to
a daemon. I'm looking for a way to intercept that
connection and to insert the bytes and the MD5 hash
there (kind of "man in the middle attack", but it's
not an attack :) I could find the way to do it sofar,
that's why I stick with a CGI-script at the moment.

Regards
Alex
 
B

Ben Morrow

I'm working at a CGI-script which would receive a 20 MB
big file via HTTP-upload, then change few bytes in it,
then calculate an MD5 hash over a region of that file
and save that value into the file as well.

At the moment I do the first task (change few bytes) like
this (the $flash is coming from the CGI.pm's filefield):

my ($fh, $filename) = tempfile(DIR => UPLOADDIR);

while (sysread $flash, $chunk, KEYSIZE) {
$both = $prev . $chunk;
if ($both =~ s/$SEARCH/$REPLACE/o) {
print $fh $both;
undef $prev;
} else {
print $fh $prev;
$prev = $chunk;
}
}
# don't forget to print the last line
print $fh $prev;

Now I need to calculate the MD5 value and store it
in the file. Is there a safe way to reuse the $fh ?
Maybe somehow by using:

open(FILEHANDLE, "<&=$fh")

? But how do I specify the mode above? I need "rb+"
so that I can store the MD5 hash into the temp.file.

Why do you need to dup the filehandle at all? Why can't you just use
$fh?

Anyway, the answer is

open my $NEWFH, '+<&=', $fh;

or, pre-5.8,

open my $NEWFH, '+<&=' . fileno $fh;
Also do I really need the new temp.file or is there
a nice way to work with CGI.pm's temp files?

If the $SEARCH and $REPLACE are the same length then you can run through
the file and simply overwrite chunks that change with syswrite. If they
are not then you have to make a copy.

Ben
 
A

A. Farber

If the $SEARCH and $REPLACE are the same length then you can run through
the file and simply overwrite chunks that change with syswrite. If they
are not then you have to make a copy.

Thank you, yes they are equal size. I haven't thought
about just running syswrite. What I still don't know though,
which buffer size to use while copying the uploaded file:

($fh, $filename) = tempfile(DIR => UPLOADDIR);

while (<$upload>) {
print $fh $_;
}

- is bad choice, because it's a binary file.
And if I use sysread/syswrite, then what $buffer
size should I use? Should I use PIPE_BUF?

while (sysread $upload, $buffer, $buf_size) {
die "syswrite failed: $!"
unless length $buffer == syswrite $fh, $buffer;
}
 
B

Ben Morrow

Thank you, yes they are equal size. I haven't thought
about just running syswrite. What I still don't know though,
which buffer size to use while copying the uploaded file:

($fh, $filename) = tempfile(DIR => UPLOADDIR);

while (<$upload>) {
print $fh $_;
}

Why are you copying it at all? Can you not simply edit the uploaded file
directly?
- is bad choice, because it's a binary file.
And if I use sysread/syswrite, then what $buffer
size should I use? Should I use PIPE_BUF?

You can make <> read be chunks by setting it to, e.g., \4096. This is
better than using sys{read,write}, as perlio will use the right buffer
size for you.
while (sysread $upload, $buffer, $buf_size) {
die "syswrite failed: $!"
unless length $buffer == syswrite $fh, $buffer;
}

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top