PHP openssl_pkcs12_export creates invalid pkcs12-file - php

I have a MySQL-DB, which contains SSL certificate private keys and the certificate. My goal is to create a PHP script, that creates a pkcs12-file and sends it to browser/download.
Thats my code:
<?php
$certid = "22";
$sqltran = mysqli_query($connection, "SELECT * FROM certificates WHERE id=$certid ")or die(mysqli_error($connection));
$row = mysqli_fetch_array($sqltran);
extract($row);
$privateKeyPass = "mypassword";
$pkey = openssl_pkey_get_private($privatekey, $privateKeyPass);
$rc = openssl_pkcs12_export($certificate, $pkcs12, $pkey, "exportpassword");
if (!($rc === true)) {
echo ('Failed to export PKCS12 Certficate Store.');
die('getpkcs12.php');
}
header('Pragma: private');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private');
header('Content-Description: File Transfer');
header('Content-Type: application/x-pkcs12');
header('Content-Disposition: attachment; filename="' . $commonname . '.p12"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . strlen($pkcs12));
print($pkcs12);
?>
It creates a file and provides a download with the correct filename; but I cannot import the p12-file in any system (invalid file).
Just tried to generate the pkcs12-file with function
openssl_pkcs12_export_to_file($certificate,$filename,$pkey, $privateKeyPass);
That worked file, so values of $certificate and $privatekey / $pkey seems to be ok.
Any idea? Whats wrong?

Related

PHP file download empty

Please help, this code downloads file but file is empty(0byte) but inside the folder its 1mb.
function dowloadbooks($id){
$allbooks ="SELECT * FROM books_table WHERE books_id = '$id' ";
$result=$this->conn->query($allbooks);
$row = array();
if($result->num_rows >0){
while($res = $result->fetch_assoc()){
$row = $res['book_upload'];
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' .$row.'');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($row));
readfile($row);
}
}
return $row;
}
I suggest you break your problem into smaller chunks:
Your file does not exist most likely or you are using the wrong path relative to your script. When I modify your example to use an existing file and exclude DB functionality, the file downloads correctly with no errors:
dowloadbooks();
function dowloadbooks(){
$row = 'c:/ExistingFile.png';
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' .$row.'');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($row));
readfile($row);
return $row;
}
Let's try the same example with non existing file:
//error_reporting(0);
dowloadbooks();
function dowloadbooks(){
$row = 'c:/NonExistingFile.png';
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' .$row.'');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($row));
readfile($row);
return $row;
}
I get two errors:
PHP Warning: filesize(): stat failed for c:/NonExistingFile.png in test.php on line 13
PHP Warning: readfile(c:/NonExistingFile.png): failed to open stream: No such file or directory in test.php on line 14
But when I disable the error reporting with error_reporting(0), suddenly the file is downloading with zero size!!!
Conclusion:
Try displaying the file path first or/and enable errors with error_reporting(-1) - you should see where the problem is.

Why my header cannot download a file?

I want to get information and download it through a file. But it just open a new window and show the information in it.
$filename = $this->input->cookie('merchant_id');
$timestamp = date("YmdHis",time());
$filename .= $timestamp.'.'.$fileType;
$title = mb_convert_encoding($title,'gbk','utf-8');
header('Content-type: application/octet-stream');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Content-Disposition: attachment; filename=' . $filename);
echo $title;
$ret = $this->download_model->QueryList($Req, $Resp);
$content = $this->GetDownLoadContentNew($ret['bill_list'], $fileType);
echo $content;
The GetDownLoadContentNew function just format the content.
So, why it cannot download?

Create content type and download with specified path in php?

I have created the text file and downloading when I execute the code. But I need to store this downloaded file in a specified folder inside the server. I have tried in many ways, but I didn't get any solution. I have mentioned my code below, Can anyone guide me?
$saving_name = $i.''.$machineid.'.'.$count_pad;
foreach($data['SalesDetails'] as $d)
{
$val = $d->inv_total - $d->inv_discount;
$explodedval = explode(".",$val);
$totalval = str_pad($explodedval['0'], 8, "0", STR_PAD_LEFT);
$totalvals = str_pad($explodedval['1'], 2, "0", STR_PAD_RIGHT);
$result = $totalval.'.'.$totalvals;
$dates = str_replace("-","",$d->date);
$out .= $i.''.$machineid.''.$dates.''.$result.' '."\r\n";
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$saving_name.'.txt');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
echo "\xEF\xBB\xBF"; // UTF-8 BOM
echo $out;
exit;
Here is the path need to move the downloading file, /var/www/html/art/assets/uploads/edi/sample.txt
Thank you for your support. Finally I got solution for this which is shown below:
$saving_name = $i.''.$machineid.'.'.$count_pad;
foreach($data['SalesDetails'] as $d)
{
$val = $d->inv_total - $d->inv_discount;
$explodedval = explode(".",$val);
$totalval = str_pad($explodedval['0'], 8, "0", STR_PAD_LEFT);
$totalvals = str_pad($explodedval['1'], 2, "0", STR_PAD_RIGHT);
$result = $totalval.'.'.$totalvals;
$dates = str_replace("-","",$d->date);
$out .= $i.''.$machineid.''.$dates.''.$result.' '."\r\n";
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$saving_name.'.txt');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
echo "\xEF\xBB\xBF"; // UTF-8 BOM
echo $out;
$backup_file = '/var/www/html/artbak/assets/uploads/edi/'.$saving_name.'.txt';
//save file
$handle = fopen($backup_file,'w+');
fwrite($handle,$out);
fclose($handle);
exit;
Now the file stored in the specified folder as well download also.

readfile() returns empty file while trying to force download

I'm trying to force download of .dwg files with the following code:
$filename = $_GET['f'];
$upload_path = wp_upload_dir();
$src = $upload_path['basedir'] . '/' . $filename;
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false);
header("Content-disposition: attachment; filename=\"{$filename}\"");
header("Content-Type: application/octet-stream");
header('Content-Transfer-Encoding: binary');
readfile($src);
die();
The path to the file is correct, but it only returns a file that is 6 byte and that is not possible to open. It should be 754 bytes. Anyone who can help me out here?
//Example file
$src = "/var/www/wp/wp-content/uploads/Glasparti-modell-Silence.dwg";
Try to add the Content-length header :
$size = filesize($src);
header("Content-length: $size");
Try with:
$name = $_GET['f'];
$url = './files/'.$name;
header("Content-type: application/octet-stream");
header("Content-disposition: attachment;filename=$name");
readfile($url);
I solved this by the following in .htaccess instead:
<FilesMatch "\.(dwg)$" >
ForceType application/octet-stream
Header add Content-Disposition "attachment"
</FilesMatch>
Can you please use .dwg file Content-Type:
application/acad
application/x-acad
application/autocad_dwg
image/x-dwg, application/dwg
application/x-dwg
application/x-autocad
image/vnd.dwg
drawing/dwg
header("Content-type: 'application/pdf'");
header("Content-Type: application/force-download");
Can you try this,
<?php
$file = '';// file path here
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}else{
echo "File not found";
}
?>
Try it !!
/**
* file download in MVC
*
* #author VECTOR Ann <ann#vector.cool>
* #since 1.0.1
*
* #param string $file 提供下載的檔案絕對路徑
* #param string $download_name 下載的檔名
* #return void
*/
function v_file_download($file,$download_name=''):void
{
if (is_file($file)) {
if($download_name=='')$download_name = date('Y_m_d',time()).".zip";
header_remove();
ob_end_clean();
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($download_name));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
ob_end_flush();
exit;
}
}

open encrypted file

I'm looking for a way to open encrypted files that are stored on a server. I'm using mcrypt to encrypt the files.
I was initially going to create a class that would open the file, decrypt it, write it to a new location, then open that. But I have convinced myself there is a better way (I just don't know what it is). It seems like there should be a way to stream it (?) to the browser once it's decrypted.
The initial setup would just link to the file location and the browser would take over (e.g. .pdf files would bring up a dialogue offering to open or save the file). If possible, I'd like it to do the same after decoding.
Pointers? Advice? Bueller?
Thanks!
edit:
This is what is working for now:
function decryptFile($path){
$folder=BASE_PATH.$path.'/'.$this->uri->segment(4);
if(!file_exists($folder.'/tmp')){
mkdir($folder.'/tmp', 0700);
chmod($folder.'/tmp', 0700);
}
$tmpfn=BASE_PATH.$path.'/'.$this->uri->segment(4).'/tmp/'.$this->uri->segment(5);
$p=BASE_PATH.$path.'/'.$this->uri->segment(4).'/'.$this->uri->segment(5);
$pc=file_get_contents($p) or die ('no gfc');
$pcue=$this->encrypt->decode($pc,$this->e_key) or die ('no decode');
$pp=fopen($tmpfn,"w") or die ('no fopen'.$tmpfn);
fwrite($pp,$pcue) or die ('no write');
fclose($pp);
if (file_exists($tmpfn)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($tmpfn));
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($tmpfn));
ob_clean();
flush();
readfile($tmpfn);
unlink($tmpfn);
exit;
}
}
But another side effect of doing it this way (I guess) is that now instead of getting an open or save dialogue, the only option is to save the file. I'd rather have the option if possible.
edit - final code:
function decryptFile(){
extract($_POST);
$folder = $this->uri->segment(3);
$clientFolder = $this->uri->segment(4);
$fileName = $this->uri->segment(5);
$filePath=BASE_PATH.$folder.'/'.$clientFolder.'/'.$fileName;
$fileContents=file_get_contents($filePath) or die ('Could not get file contents.');
$ue_fileContents=$this->encrypt->decode($pc,$this->e_key) or die ('Could not decode.');
header('Content-Description: File Transfer');
header('Content-Type: '.$type);
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: ' . strlen($ue_fileContents));
echo $ue_fileContents;
exit;
}
Why do you have to write to a temporary file? You can simply do something like this,
function decryptFile($path){
$folder=BASE_PATH.$path.'/'.$this->uri->segment(4);
$tmpfn=BASE_PATH.$path.'/'.$this->uri->segment(4).'/tmp/'.$this->uri->segment(5);
$p=BASE_PATH.$path.'/'.$this->uri->segment(4).'/'.$this->uri->segment(5);
$pc=file_get_contents($p) or die ('no gfc');
$pcue=$this->encrypt->decode($pc,$this->e_key) or die ('no decde');
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($tmpfn));
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: ' . strlen($pcue));
echo $pcue;
exit;
}
But another side effect of doing it this way (I guess) is that now instead of getting an open or save dialogue, the only option is to save the file. I'd rather have the option if possible
Try to replace
header('Content-Type: application/octet-stream');
with the actual type of the file. For instance, if it's a PDF:
header('Content-type: application/pdf');
You may also want to drop the line:
header('Content-Disposition: attachment; filename='.basename($tmpfn));
so that no dialog is shown by the browser.

Categories