Hi
I am having trouble with a file transfer script, as you can see, I am
trying trying to keep the code as simple as possible.
But everytime I download a file with it, it is corrupt. For example, when
I download a small .rar file, just to test, it is always corrupt
('Unexpected end of archive'). I also cleared my browser cache just to be
sure, but same problem.
I just can't get my head around why it wouldn't be working as it is...
A couple of questions:
Have I got too many header requests?
Do I need to worry about output buffering, which is possibly corrupting
the file output (if so, please tell me what to do!)?
Is there an easier way to get returned response header and get a
redirected link, instead of finding and cutting strings?
Is there maybe something wrong with the structure or order of the header
requests, and/or returned headers etc?
Here is what I have so far:
<?php
//ob_start();
//ob_end_flush();
//ob_implicit_flush(TRUE);
$rslogin = '';
$rspass = '';
$link = addslashes(trim($_POST['link']));
function cut_str($str, $left, $right)
{
$str = substr(stristr($str, $left), strlen($left));
$leftLen = strlen(stristr($str, $right));
$leftLen = $leftLen ? -($leftLen) : strlen($str);
$str = substr($str, 0, $leftLen);
return $str;
}
// Get the full premium link, and store it in $full_link after the
redirect. *Surely* there is an easier way to get redirections?
if(strlen($link)>0)
{
$url = @parse_url($link);
$fp = @fsockopen($url['host'], 80, $errno, $errstr);
if (!$fp)
{
$errormsg = "Error: <b>$errstr</b>, please try again later.";
echo $errormsg;
exit;
}
$vars = "dl.start=PREMIUM&uri={$url['path']}&directstart=1";
$out = "POST {$url['path']} HTTP/1.1\r\n";
$out .= "Host: {$url['host']}\r\n";
$out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows
NT 5.1)\r\n";
$out .= "Authorization: Basic
".base64_encode("{$rslogin}:{$rspass}")."\r\n";
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
$out .= "Content-Length: ".strlen($vars)."\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
fwrite($fp, $out.$vars);
while (!feof($fp))
{
$string .= fgets($fp, 256);
}
//Tell us what data is returned
//print($string);
@fclose($fp);
if (stristr($string, "Location:"))
{
$redirect = trim(cut_str($string, "Location:", "\n"));
$full_link = addslashes(trim($redirect));
}
//print($string);
//print("<html><body><h1>".$full_link."</h1>");
if ($full_link)
{
// Get info about the file we want to download:
$furl = parse_url($full_link);
$fvars = "dl.start=PREMIUM&uri={$furl['path']}&directstart=1";
$head = "Host: {$furl['host']}\r\n";
$head .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT
5.1)\r\n";
$head .= "Authorization: Basic
".base64_encode("{$rslogin}:{$rspass}")."\r\n";
$head .= "Content-Type: application/x-www-form-urlencoded\r\n";
$head .= "Content-Length: ".strlen($fvars)."\r\n";
$head .= "Connection: close\r\n\r\n";
$fp = @fsockopen($furl['host'], 80, $errno, $errstr);
if (!$fp)
{
echo "The script says <b>$errstr</b>, please try again later.";
exit;
}
fwrite($fp, "POST {$furl['path']} HTTP/1.1\r\n");
fwrite($fp, $head.$fvars);
while (!feof($fp))
{
//Keep reading the info until we get the filename and size from
the returned Header - is there no easy way
//of doing this? I also don't like the way I have to 'find' the
redirected link (above).??
$tmp .= fgets($fp, 256);
$d = explode("\r\n\r\n", $tmp);
// I tried changing this to if ($d), { etc.., (instead of
$d[1]) and the download of the rar file *wasn't* corrupt, it just had a
filetype of x-rar-compressed instead of
//application/octet-stream, and the filesize was 'unknown' -
now this is just confusing me...! So i think (and guess) the problem of
the file corruption is here,
//because it must add some data to the filestream which
corrupts it. Darn.
if($d[1])
{
preg_match("#filename=(.+?)\n#", $tmp, $fname);
preg_match("#Content-Length: (.+?)\n#", $tmp, $fsize);
$h['filename'] = $fname[1] != "" ? $fname[1] :
basename($furl['path']);
$h['fsize'] = $fsize[1];
break;
}
}
@fclose($fp);
$filename = $h['filename'];
$fsize = $h['fsize'];
//Now automatically download the file:
@header("Cache-Control:");
@header("Cache-Control: public");
@header("Content-Type: application/octet-stream");
@header("Content-Disposition: attachment; filename=".$filename);
@header("Accept-Ranges: bytes");
if(isset($_SERVER['HTTP_RANGE']))
{
list($a, $range)=explode("=",$_SERVER['HTTP_RANGE']);
$range = str_replace("-", "", $range);
$new_length = $fsize - $range;
@header("HTTP/1.1 206 Partial Content");
@header("Content-Length: $new_length");
}
else
{
@header("Content-Length: ".$fsize);
}
$f2vars = "dl.start=PREMIUM&uri={$furl['path']}&directstart=1";
$head2 = "Host: {$furl['host']}\r\n";
$head2 .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows
NT 5.1)\r\n";
$head2 .= "Authorization: Basic
".base64_encode("{$rslogin}:{$rspass}")."\r\n";
$head2 .= "Content-Type: application/x-www-form-urlencoded\r\n";
if($range != "") $head2 .= "Range: bytes={$range}-\r\n";
$head2 .= "Content-Length: ".strlen($fvars)."\r\n";
$head2 .= "Connection: close\r\n\r\n";
$fp = @fsockopen($furl['host'], 80, $errno, $errstr);
if (!$fp)
{
echo "<span style='color:#688000; background-color:#BBDB54;
font-size : 10pt; text-decoration: none; font-family: Trebuchet MS;'>The
script says <b>$errstr</b>, please try again later.</span>";
exit;
}
@stream_set_timeout($fp, 120);
fwrite($fp, "POST {$furl['path']} HTTP/1.1\r\n");
fwrite($fp, $head2.$f2vars);
fflush($fp);
while (!feof($fp))
{
$download = fread($fp, 2048);
echo $download;
//ob_flush(); //php.net suggestion
}
//These two buggers were here originally, but I don't even know if I am
supposed to have them here.
flush();
ob_flush();
@fclose($fp);
exit;
}
}
else
{
$data = "<form method=\"post\">\n";
$data .= "<input type=\"text\" id=\"link\"
style=\"text-align:center\" name=\"link\" size=\"60\"
onfocus=\"if(this.value=='Enter rapidshare.com URL
here'){this.value=''}\">\n";
$data .= "<br><input type=\"submit\" value=\"Download\"></form>";
echo $data;
}
?>
Thanks to anyone who has already helped, I hope some genius can spot an
obvious error, because this is just beyond me!
:)