Why this file download CGI works with Firefox and fails with IE ?

U

Us

Hello everybody,

I've a problem with a file download script written in Perl. When I call
it from Firefox it's OK, but when I call it from IE, it's not.

The IE download dialog is launched, but IE try to search info about the
file and fails to do-it. Thus, I get an error message saying "IE cannot
download download.cgi?test.rar from www..."

What's the problem with this script and IE ?


The code is this :
#!/usr/bin/perl -w

use CGI ':standard';

my $ID = param('ID');
my $files_location = "../httpdocs/repository";
my @fileholder;

if ($ID eq ''){
print "Content-type: text/html\n\n";
print "no file parameter";}
else{
open(DLFILE, "<$files_location/$ID") || Error('open', 'file');
binmode DLFILE;
@fileholder = <DLFILE>;
close (DLFILE) || Error ('close', 'file');

open (LOG, ">>download.log") || Error('open', 'file');
print LOG "$ID\n";
close (LOG);

binmode STDOUT;
print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$ID\n\n";
print @fileholder}

sub Error{
print "Content-type: text/html\n\n";
print "server can't $_[0] the $_[1]: $! \n";
exit;}

It's called using url like (here a fictive one) :
http://www.mydomain.org/cgi-bin/download.cgi?ID=test.rar
knowing test.rar is present in the repository directory.
 
A

A. Sinan Unur

Hello everybody, ....

What's the problem with this script and IE ?

The script has many problems other than the one you are experiencing.
The code is this :
#!/usr/bin/perl -w

use strict;
use CGI ':standard';

my $ID = param('ID');

You are not running any checks against ID.
my $files_location = "../httpdocs/repository";
my @fileholder;

if ($ID eq ''){
print "Content-type: text/html\n\n";

Why are you lying about the content type?
print "no file parameter";}
else{
open(DLFILE, "<$files_location/$ID") || Error('open', 'file');

Oh, nice. This way, I can download any file on your system.
binmode DLFILE;
@fileholder = <DLFILE>;

There is no need to slurp the whole file. Just read chunks of it (using
sysread and echo back out.
close (DLFILE) || Error ('close', 'file');

open (LOG, ">>download.log") || Error('open', 'file');
print LOG "$ID\n";
close (LOG);

binmode STDOUT;
print "Content-Type:application/x-download\n";

AFAIK, a space is needed between the colon and the MIME type.

Use CGI.pm to generate headers.

Sinan
 
U

Us

The script has many problems other than the one you are experiencing.

OK, it seems to be a bad CGI (from Web), but does all you say explain
the reason why it doesn't works with IE while it works (even if ugly)
with Firefox ?
 
J

Jürgen Exner

Us said:
OK, it seems to be a bad CGI (from Web), but does all you say explain
the reason why it doesn't works with IE while it works (even if ugly)
with Firefox ?

You may want to ask in a nNewsgroup that actually deals with web
programming, CGI, and differences between different web browsers.

Or to put it the other way: if this script were written in C or Modula
producing exactly the same behaviour/output as your Perl script, would you
expect IE "to work"?

jue
 
S

smallpond

Hello everybody,

I've a problem with a file download script written in Perl. When I call
it from Firefox it's OK, but when I call it from IE, it's not.

The IE download dialog is launched, but IE try to search info about the
file and fails to do-it. Thus, I get an error message saying "IE cannot
download download.cgi?test.rar from www..."

What's the problem with this script and IE ?

The code is this :
#!/usr/bin/perl -w

use CGI ':standard';

my $ID = param('ID');
my $files_location = "../httpdocs/repository";
my @fileholder;

if ($ID eq ''){
print "Content-type: text/html\n\n";
print "no file parameter";}
else{
open(DLFILE, "<$files_location/$ID") || Error('open', 'file');
binmode DLFILE;
@fileholder = <DLFILE>;
close (DLFILE) || Error ('close', 'file');

open (LOG, ">>download.log") || Error('open', 'file');
print LOG "$ID\n";
close (LOG);

binmode STDOUT;
print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$ID\n\n";
print @fileholder}

sub Error{
print "Content-type: text/html\n\n";
print "server can't $_[0] the $_[1]: $! \n";
exit;}

It's called using url like (here a fictive one) :http://www.mydomain.org/cgi-bin/download.cgi?ID=test.rar
knowing test.rar is present in the repository directory.

What's in the webserver error log?
 
U

Us

What's in the webserver error log?

Unfortunately, nothing in error_log.

The download dialog box is well displayed by IE, but it search for file
info and one second later, says it cannot found it.
 
U

Us

You may want to ask in a nNewsgroup that actually deals with web
programming, CGI, and differences between different web browsers

Good idea, I'll do it in parralel with the current topic. Thanks you.
 
U

Us

take a look to packet log what headers server sent.

Thank you for. The different headers received are those (notice I've
switched to a test.zip rather than test.rar just because I had a smaller
one ready for testing) :

When I download directly :
(Status-Line) HTTP/1.0 200 OK
Accept-Ranges bytes
Connection keep-alive
Content-Length 145281
Content-Type application/zip
Date Sat, 17 Nov 2007 10:13:19 GMT
ETag "578da31-23781-43bc5911c7500"
Last-Modified Fri, 05 Oct 2007 21:27:16 GMT
Server Apache/2.2.3
Via 1.0 GATEDSK:800 (squid/2.6.STABLE13)
X-Cache MISS from GATEDSK
X-Pad avoid browser bug

When I try to download through the script
(Status-Line) HTTP/1.0 200 OK
Connection close
Content-Disposition attachment; filename="test.zip"
Content-Encoding gzip
Content-Transfer-Encoding binary
Content-Type application/x-download
Date Sat, 17 Nov 2007 09:59:37 GMT
Expires 0
Pragma public
Server Apache/2.2.3
Vary Accept-Encoding
Via 1.0 GATEDSK:800 (squid/2.6.STABLE13)
X-Cache MISS from GATEDSK

In the script I've tried indicating content-length or not, but it's the
same. I've also added "Pragma: public" while I've read it was required
by IE, but not any evolution).

However, searching Google, I've seen this IE behavior is largely a
problem for a lot of people... But I don't see any clear solution until
now... I continue
 
U

Us

This work for me

Interesting, because it doesn't work on my side (I've tried under
Windows too, to be on same case as yours).

I've tried a first time with the path with c:\... as you, and a second
time changing to something in the web space like this (w/o some typo
found) :

#!/usr/bin/perl
use strict;
my $file='../../htdocs/test/test.zip';
my $name=$file;
$name=~s/^.+\/(.+)$/$1/;
my $size=(stat $file)[7];
binmode STDOUT;
print "Content-Type: application/zip\n",
"Accept-Ranges: bytes\n",
"Cache-Control: no-cache, no-store, no-transform, must-revalidate\n",
"Content-disposition: attachment; filename=$name\n",
"Content-Length: $size\n\n";
my $buf;
open(F,"<$file");
binmode F;
read(F,$buf, 1024);
while ($buf)
{
print $buf;
read(F,$buf, 1024);
}
close F;

And it continue do do the same : IE start download-dlg, then search for
info and sto with an error saying "Internet Explorer cannot download
download_test.pl from www.mysite..."

I've tried with a lot of HTTP headers now and not any solution :-(
 
U

Us

I've tried with a lot of HTTP headers now and not any solution :-(

Continuing, I've found something ; even if it's not about Perl, it may
interest some.

Searching, I've finally found an HTTP header which works under a local
Apache/Windows :

print "Content-Type: application/octet-stream\n";
print "Content-Length: $size\n";
print "Content-Disposition: attachment; filename=$file\n";
print "Pragma: public\n";
print "Cache-Control: must-revalidate, post-check=0, pre-check=0\n";
print "Expires: 0\n\n";

The problem is that it still didn't work under remote Apache/FreeBSD. IE
fails to find info about file, then display an error.

Searching again and again, I've found an MS article at
http://support.microsoft.com/default.aspx?scid=kb;en-us;812935 talking
about ""Internet Explorer Cannot Download" Error Message When You Use an
HTTPS URL to Open an Office Document or PDF File".

Well, in my case, it's not an HTTPS url and not about PDF/DOC/XLS/MDB
document... But, I've tried what they say :

********
Article ID : 812935
Last Review : November 15, 2007
Revision : 2.5

CAUSE
This issue may occur if any one or more of the following conditions are
true: ? The Do not save encrypted pages to disk check box is selected in
Internet Explorer 6.0 SP1.
? The server sends the "Cache-Control: No Store" header.
? The server sends the "Cache-Control: No Cache" header.

RESOLUTION
A supported hotfix is now available from Microsoft. [they don't give any
url for doanload]

WORKAROUND
To work around this problem, make sure that Do Not Save Encrypted Files
check box is not checked and that the server does not send the "Cache-
Control: No Store" or the "Cache-Control: No Cache" header.

You may also be able to work around this problem by using an HREF to
load the document.

Note This method does not work if the server uses the "Cache-Control: No
Cache" header.
**********


Thus, I've unchecked the "Do Not Save Encrypted Files" IE's check box in
its options... And magically, it works !

Good for me, but wrong for my visitors if they have this case checked.
How to manage this IE6 Bug according to you ???
 
U

Us

Searching again and again, I've found an MS article at
http://support.microsoft.com/default.aspx?scid=kb;en-us;812935 talking
about ""Internet Explorer Cannot Download" Error Message When You Use an
HTTPS URL to Open an Office Document or PDF File".

Well, in my case, it's not an HTTPS url and not about PDF/DOC/XLS/MDB
document... But, I've tried what they say :

Not sure if it's the killer solution, but I've just found an HTTP header
which seems to work with IE6 and the "do not save crypted page" checked.

Content-Type: application/octet-stream
Content-Length: $size
Content-Disposition: attachment; filename=$file
Cache-Control: public
Pragma: public
Expires: 0


[maybe solved]
 
U

Us

Are you sure that this is a system path to file? You can't to use URL path.
For example (on unix) if your file test.zip is stored in
/var/www/htdocs/test/ then you must use

my $file='/var/www/htdocs/test/test.zip';

I think you can use indifferently full qualified path or relative one
from root or the script itself (what I've done here)
My second advice is to use .cgi extension instead of .pl for web perl
scripts

An usual to remember what's in Perl and what's not :)
and my third advice is to use slash / instead of backslash \. This
work on all operating systems (*nix, Win, Mac).

It's what I do most of the time ;)
 
U

Us

Yes, if course. I wanted to accent that must be used system path instead of
"http path" ;-)
But be careful that perl script is in some directory but can be run (by
Apache) from other directory. In this case the relative path is not good
idea. I'm used to use some "our" variable where I have stored absolute path
to web root directory and all other paths I create from this variable. For
example:

# virtual server for domain mydomain.com
our $webroot = '/var/www/mydomain/home/';
...
my $downloadpath = $webroot . 'download/';

# virtual server for domain otherdomain.com
our $webroot = '/var/www/otherdomain/home/';
...
my $downloadpath = $webroot . 'download/';

I think you understand me ;-)

Understood ! Well noted, I'll take a look on this later ;)

Well, I thought it was OK yesterday and it's not today. It works now in
IE with a local Apache/Win, but not a remote Apache/FreeBSD with IE6 at
the other side.

Here a mini test (changed a lot and unsecure but a test) :

#!/usr/bin/perl -w
# this code is an unsecure mini one only for internal test with IE6
use strict;
use CGI::Carp qw/fatalsToBrowser/;
my $loc = "../../../htdocs/repository/";
my $file = "test.zip";
my $size = -s $loc.$file;
print "Content-Disposition: attachment; filename=$file\n";
print "Content-Type: application/octet-stream\n";
print "Content-Length: $size\n\n";
open FILE, "<$loc$file";
binmode FILE;
binmode STDOUT;
print while read FILE, $_, 1024;
close FILE;
exit 0;
 
A

A. Sinan Unur

#############################
try this
open FILE, "<$loc$file" or die "Have not privileges to read?";

open my $file, '<', "$loc$file"
or die "Cannot open '$loc$file': $!";

instead of guessing the error, include $! in the error message.

Sinan
 
U

Us

open my $file, '<', "$loc$file"
or die "Cannot open '$loc$file': $!";

instead of guessing the error, include $! in the error message.

Sinan

It's what I do in the final script. The previous one was just a
minimalist one for quick test
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top