Is the File Transfer code correct in my PHP? - php

I have this page that is supposed to be a download for a song. The download works in firefox for me but in chrome and safari nothing happens..here is my code
public function download() {
if (isset($this->request->get['order_download_id'])) {
$order_download_id = $this->request->get['order_download_id'];
} else {
$order_download_id = 0;
}
$download_info = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_download od LEFT JOIN `" . DB_PREFIX . "order` o ON (od.order_id = o.order_id) WHERE o.customer_id = '" . (int)$this->customer->getId(). "' AND o.order_status_id > '0' AND o.order_status_id = '" . (int)$this->config->get('config_download_status') . "' AND od.order_download_id = '" . (int)$order_download_id . "'");
if ($download_info->row) {
$file = DIR_DOWNLOAD . $download_info->row['filename'];
$mask = basename($download_info->row['mask']);
$mime = 'application/octet-stream';
$encoding = 'binary';
if (!headers_sent()) {
if (file_exists($file)) {
header('Pragma: public');
header('Expires: 0');
header('Content-Description: File Transfer');
header('Content-Type: ' . $mime);
header('Content-Transfer-Encoding: ' . $encoding);
header('Content-Disposition: attachment; filename="' . ($mask ? $mask : basename($file)) . '"');
header('Content-Length: ' . filesize($file));
$file = readfile($file, 'rb');
print($file);
} else {
exit('Error: Could not find file ' . $file . '!');
}
} else {
exit('Error: Headers already sent out!');
}
}
}
I have tried all kinds of different things to get this to work but nothing is happening in the two browsers...any ideas or help will be appreciated...

readfile returns the number of bytes sent, and needs not to be printed out. You should remove the line print($file);. Otherwise, you'll send more bytes than the Content-Length header specifies, and that will lead some HTTP clients to discard your answer.
Also, consider strange file names such as
"\r\nLocation: http://evil.com\r\n\r\n<script>alert('XSS');</script>
Are you handling that correctly?

See your syntax near
header('Content-Disposition: attachment; filename="'.$file_name_with_space. '"');
OR it can be
header("Content-Disposition: attachment; filename='".$file_name_with_space."'" );
Here the game is in Quotes only it will be treated as part of the string if it is written properly else will crash.
It works in all browser. IE, FF, Chrome, SAFARI I checked it personally so goahead.

Related

Force download attachments from specific folder in a Wordpress

I wanna to add Download link button using
Download
After Searching on the internet I got that code:
$file_obj = new FileData($_REQUEST['id']);
// Added this check to keep unauthorized users from downloading - Thanks to Chad Bloomquist
checkUserPermission($_REQUEST['id'], $file_obj->READ_RIGHT, $file_obj);
$realname = $file_obj->getName();
if (isset($revision_id)) {
$filename = $revision_dir . $request_id . ".dat";
} elseif ($file_obj->isArchived()) {
$filename = $GLOBALS['CONFIG']['archiveDir'] . $_REQUEST['id'] . ".dat";
} else {
$filename = $GLOBALS['CONFIG']['dataDir'] . $_REQUEST['id'] . ".dat";
}
if (file_exists($filename)) {
// send headers to browser to initiate file download
header('Cache-control: private');
header('Content-Type: '.$_GET['mimetype']);
header('Content-Disposition: attachment; filename="' . $realname . '"');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
readfile($filename);
} else {
echo msg('message_file_does_not_exist');
}
Here $revision_dir = $GLOBALS['CONFIG']['revisionDir'] . '/'. $_REQUEST['id'] . '/';
But I wanna download files from sitename.com/pdm-uploads/
Leave the above code and simply add download in <a> tag.
<a href="<?php echo home_url( '/' ).'path/'. $download->realname ?>" download>Download Now</>

Cant pass value as variable in this php script

Like the question says, I can't seem to pass a value in a variable in the following script. If I echo the variable, it exists as expected. If i copy and paste the echoed value into the code where $my_var is, it works. But it wont work with $my_var ?!?!?
Context- code requires another file to create a pdf, attaches it to an email and sends it, and then displays it in the browser. Have removed most of the code for brevity
$my_var = $_POST['quote_number'];
$filename = 'Quote_no' . $my_var . '.pdf';
$file = $_SERVER['DOCUMENT_ROOT'] . '/quotes/' . $filename ;
require('instant_quote.php');
function send_quote($my_var) {
//my_function code
};
send_quote($my_var);
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));
header('Accept-Ranges: bytes');
#readfile($file);
The syntax highlighting in your example was helpful, you have incorrect matching quotes:
$filename = "Quote_no' . $my_var . '.pdf";
... should be:
$filename = 'Quote_no' . $my_var . '.pdf';
Don't know why this worked, but it did...
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $file . '"');
header('Content-Length: ' . filesize($filename));
#readfile($filename);
Just removed the transfer encoding and accept-ranges from the headers, and it started accepting my variable as a value... go figure

WKHTMLTOPDF with PHP not accepting args for page size?

I'm using WKHTMLTOPDF for a client. My PHP is quite rough... The problem is, my arguments aren't working, and in the below example they could be wrong, but none are working... such as zoom, page-size, etc. So for example, in the switch statement, you can see the Building type. I want this to output as a standard US Letter type. --page-size A, or is it --page-size "A", or --page-size "Letter"? But regardless, I'm not passing the arguments properly, because no matter what I change, (i.e. --zoom .10) for testing, nothing changes. Any help is appreciated!
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
try {
$mydir = getcwd();
// Figure out the URL
$url = $_GET['url'];
$url = str_replace(';', ' ', $url);
// Figure out the mode
$mode = isset($_GET['mode']) ? $_GET['mode'] : 'standard';
// Figure out the mode
$name = isset($_GET['name']) ? '-' . $_GET['name'] . '-' : '';
// Generate GUID filename
$file = $mydir . '\\' . uniqid('', true) . '.pdf';
// Build arguments
$args = '
--load-error-handling ignore
';
switch($mode) {
case 'Site';
$args .= ' --title "Site Report"';
$filename = 'Site-Report' . $name . '.pdf';
break;
case 'Building';
$args .= ' --title "Building Report" --page-size "A"';
$filename = 'Building-Report' . $name . '.pdf';
break;
case 'standard';
default;
$args .= ' --title "Development Report" --zoom .55';
$filename = 'Development-Web-Report.pdf';
break;
}
// Build the command
putenv("path=" . getenv("path") . ';"C:\Program Files (x86)\wkhtmltopdf"');
$cmd = escapeshellcmd('CMD /c wkhtmltopdf ' . $url . ' ' . $file);
$com = new COM("WScript.Shell");
$shell = $com->Exec($cmd);
$shell->StdErr->ReadAll;
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename=' . $filename);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
unlink($file);
exit;
}
} catch (Exception $e) {
echo $e->getMessage();
}
?>
You are not even attaching your arguments to command string.
Try this:
$cmd = escapeshellcmd('CMD /c wkhtmltopdf ' . $args . ' ' . $url . ' ' . $file);
Also good to know that on Windows you cannot use absolute paths (like C:\) to point to a html file since it expects url's or relative paths, so you must use wkhtmltopdf file:///d:/in.html out.pdf, also note the / instead of \. This is true even for the latest version (0.11.0 rc1), although in future it may support absolute system paths for win.

Error in downloading.... The archived file is corrupted or damaged

My download.php is not working . After downloading is completed, the error on opening file is 'the archived file is corrupted or damaged '.
I dont know the reason of an error. so please help me. This code was a hard code. i tested this code by giving the name of the images. it worked right but when i retreived the images from database and tried to run this code , something went wrong.
<?php
echo "<br/>" , $product_id=$_REQUEST['product_id'];
echo "<br/>" , $query= ("SELECT image_name FROM " . $db_prefix ."product WHERE image_id = $product_id");
$test = class_exists('ZipArchive');
///$url='upload_images/';
$url = $_SERVER['DOCUMENT_ROOT'].'photohive/upload_images/';
$zip = new ZipArchive;
$zip->open($_SERVER['DOCUMENT_ROOT'].'photohive/downloads/file_' . time() . '.zip', ZipArchive::CREATE);
$result = mysql_query($query);
while( $row= #mysql_fetch_assoc($result))
{
//echo $url. $row['image_name'];
$file_name = $url.$row['image_name'];
if(file_exists($file_name)){
//$zip->addFile($file_name);
//$zip->addFromString(basename($file_name), file_get_contents($file_name));
$zip->addFile(realpath($file_name), $file_name);
}
}
$zip->close();
$encoding = 'binary';
$filename = $_SERVER['DOCUMENT_ROOT'].'photohive/downloads/file_' . time() . '.zip';
header('Pragma: public');
header('Expires: 0');
header('Content-Description: File Transfer');
header('Content-Disposition: filename="' . basename($filename). '"');
header('Content-Type: application/x-zip' );
header('Content-Transfer-Encoding: ' . $encoding);
header('Content-Length: ' . filesize($filename));
$file = readfile($filename);
//print($file);
exit;
?>
In your code you are using this string to get the filename twice: $_SERVER['DOCUMENT_ROOT'].'photohive/downloads/file_' . time() . '.zip';
In the second time, the time() probably will return the different timestamp, as some seconds will pass while you are compress the images.
Also using the time() method will bring the conflict on hi traffic sites, where you could have a possibility to get two or more requests in one second.
I suggest you to use the tempnam() function to generate the file. And remember to delete it after download is completed.
Here is a code:
$filename = tempnam($_SERVER['DOCUMENT_ROOT'].'photohive/downloads', "zip");
...
$zip->open($filename, ZipArchive::OVERWRITE);
And remove this line:
$filename = $_SERVER['DOCUMENT_ROOT'].'photohive/downloads/file_' . time() . '.zip';
after $encoding = 'binary';

Form downloads same ZIP over and over

Thanks to the users community on this forum, I wrote a very simple web form that allows my user to view text files from within their Internet browser.
I have now two functions whereby the text files returned by the search are compressed into a ZIP. Here's my code
function getFilesFromSite() {
$result = null;
$ZIPresult = null;
if (empty($_POST['DBSite'])) { return null; }
$mydir = MYDIR;
$dir = opendir($mydir);
$DBSite = $_POST['DBSite'];
$getfilename = mysql_query("select filename from search_table where site='" . $DBSite . "'") or die(mysql_error());
while ($row = mysql_fetch_array($getfilename)) {
$filename = $row['filename'];
$result .= '<tr><td>' . $filename . '</td></tr>';
$ZIPresult .= basename($mydir) . '/' . $filename.' ';
}
if ($result) {
$result = "<table><tbody><tr><td>Search Results.</td></tr> $result</table>";
shell_exec("/bin/rm -f SearchResult.zip;/usr/bin/zip -9 SearchResult.zip ". $ZIPresult ." > /dev/null ");
//header for forced download
header("Pragma: public");
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
$fileName = 'SearchResult.zip';
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Transfer-Encoding: binary");
header('Content-type: application/zip');
header("Content-length: " . filesize($fileName));
header('Content-Disposition: attachment; filename="' . $fileName . '"');
ob_start(); // Starts output buffering.
readfile($fileName); // "Outputs" the file.
$content = ob_get_flush(); // Grabs the output and assigns it to a variable.
print base64_encode($content);
}
function getFilesFromError() {
//Just a copy paste from above with different input parameter...
}
The problem is that the ZIP file with the contents from whatever search was done first gets downloaded over and over again. For instance, the results from getFilesFromSite() will always get downloaded even though I did a search with getFilesFromError() afterwards.
I suspect my headers are incorrectly set but I am not sure where.
PS: The new ZipArchive() library/class is not available on our production environment so I chose to use the Unix utility ZIP instead.
Using Base64 was actually not working for reasons well stated here. Instead, I turned zlib compression off and reverted back to using binary as output format. Finally, I set Content-Type to application/octet-stream in my header. Everything is working fine now ; here's my code:
function getFiles() {
ini_set('zlib.output_compression', 'Off');
$result = null;
$ZIPresult = null;
$cleanup = null;
$output = null;
$fileName = null;
//remove old zip if any
$cleanup = shell_exec("/bin/rm -f SearchResult.zip");
error_log("SHELL OUTPUT=>" . $cleanup, 0);
//test
if (empty($_POST['DBRIDs'])) { return null; }
$mydir = MYDIR; // set from the CONSTANT
$dir = opendir($mydir);
$DBRIDs = $_POST['DBRIDs'];
$getfilename = mysql_query("select /*! SQL_CACHE */ filename from automation where rid in (" . $DBRIDs . ")") or die(mysql_error());
while ($row = mysql_fetch_array($getfilename)) {
$filename = $row['filename'];
$result .= '<tr><td>' . $filename . '</td></tr>';
$ZIPresult .= basename($mydir) . '/' . $filename.' ';
}
if ($result) {
$result = "<table><tbody><tr><td>Search Results.</td></tr> $result</table>";
$output = shell_exec("/usr/bin/zip SearchResult.zip ". $ZIPresult ." ");
error_log("SHELL OUTPUT=>" . $output, 0);
$fileName = 'SearchResult.zip';
error_log("ZIP FILENAME=>" . $fileName, 0);
if (file_exists($fileName)) {
//header for forced download
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fileName));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($fileName));
ob_clean();
flush();
readfile($fileName);
exit;
}
}
return $result;
}
Thanks to all for taking the time!!

Categories