I was creating a zip archive with php 7.4 (lib-zip version 1.6.1) without any problems.
Now I try to protect these zip archive with a password. Not just for encrypting with php, but in general. I found this tutorial. It does what it should, but I could not read the files of the zip archive any more. If I doubleclick on the archive, the password prompt opens up, but it does not work with the password from the source code. I also copy and pasted it to prevent any keyboard struggle.
<?php
$zip = new ZipArchive();
$filePath = sprintf('%s/test/', __DIR__);
$fileName = 'test.zip';
$absoluteFilePath = $filePath . $fileName;
$excludeFolderNames = [
'.',
'..',
'.DS_Store',
$fileName,
];
$zipFlag = ZipArchive::CREATE;
if (file_exists($absoluteFilePath)) {
$zipFlag = ZipArchive::OVERWRITE;
}
$createFile = $zip->open($absoluteFilePath, $zipFlag);
if (true !== $createFile) {
throw new RuntimeException(sprintf('could not open file in "%s" caused by %s', $fileName, $createFile));
}
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($filePath));
$password = 'top-secret';
if (!$zip->setPassword($password)) {
throw new RuntimeException('Set password failed');
}
/** #var SplFileInfo $value */
foreach ($iterator as $key => $value) {
if (in_array($value->getFilename(), $excludeFolderNames)) {
continue;
}
$cleanFilePath = realpath($key);
if (!$cleanFilePath) {
throw new RuntimeException(sprintf('could not create real path from filepath: %s', $key));
}
$zipName = str_replace($filePath, '', $cleanFilePath);
if (!$zip->addFile($cleanFilePath, $zipName)) {
throw new RuntimeException(sprintf('Add file failed: %s', $cleanFilePath));
}
if (!$zip->setEncryptionName($zipName, ZipArchive::EM_AES_256)) {
throw new RuntimeException(sprintf('Set encryption failed: %s', $zipName));
}
}
$zip->close();
Does someone has the same problem or am I the problem?
UPDATE I:
I tought it solves my problem to save the zip-file outside the folder I want to zip. So I changed the following line:
$absoluteFilePath = sprintf('%s/%s', __DIR__, $fileName);
After a while the error occured again.
One possible reason I discovered, were .DS_Store files. In my example I exclude them. But the error occured again.
UPDATE II:
One further problem is, that there is no password prompt, if all files are empty.
UPDATE III:
Same code works with files without line break, but the error occurs, if the file has multiple lines.
I found help at the php-bugtracker. It turns out that I can extract all the files with an zip-extension like the comments tryed to tell me before. Now I wait for the new libzip version 1.7.0, where the default zip encryption is available. After this I hope I can extract my files without any extension.
Related
I am working on zip file creation and downloading using PHP (Laravel).
Zip created and download works well. But the problem is in lhaplus software. When extracting the zip file using lhaplus, it has been changing the file name. But in another extractor like 7zip, WinRAR works well. In lhaplus software shows "03510063220_00016501tñ+sÉìtñ+sÉì_spt.pdf" but it should be 03510063220_00016501社名社名_spt.pdf.
Please help in this case. Any suggestion is appreciated.
The code is given below:
$date_time = static::getCurrentTime();
$zip_name = $date_time."_spt";
$zip = new ZipArchive;
if(!file_exists('zip/downloadedZip')){
mkdir('zip/downloadedZip',0777,true);
}
$zipFileName = 'zip/downloadedZip/'.$zip_name.'.zip';
if ($zip->open(public_path($zipFileName), ZipArchive::CREATE) === TRUE){
$fileName = "pdf/03510063220_00016501社名社名_spt.pdf";
$baseName = "03510063220_00016501社名社名_spt.pdf";
if (!$zip->addFile($fileName, mb_convert_encoding($baseName, "SJIS", "UTF-8"))) {
throw new \RuntimeException(sprintf('Add file failed: %s', $fileName));
}
$zip->close();
}
return URL($zipFileName);
I am trying to extract zip file in codeigniter 4... I have the code below
$file_name = session()->get('file_name');
// Zip file name
$filename = "/public/$file_name";
$zip = new \ZipArchive;
$res = $zip->open($filename);
if ($res === true) {
// Unzip path
$path = "/public";
// Extract file
$zip->extractTo($path);
$zip->close();
return 'Site Updated Successfully';
} else {
return "failed to update $filename!";
}
}
but I get this result: return "failed to update $filename!";
Please can someone help me fix the issue with the code.
This has nothing specifically to do with Codeigniter. It's just using PHP and ZipArchive. The code looks OK - be sure the file is really in the /public/ directory and that it is a zip archive. The PHP site has examples that are like $zip = new ZipArchive; (without the \ char); maybe try that.
Ok so this is making me crazy... I abstracted the code because it comes from a big project. But in my project I ended up commenting everything and only have this left which is still causing problems and I have no idea why.
$f = fopen('tmp/'.$name.'.zip', 'wb');
fwrite($f, $myzip);
fclose($f); //I can open this file manually and everything is fine
$zip = new ZipArchive;
$res = $zip->open('tmp/'.$name.'.zip'); //$res is "1"
$zip->extractTo("final/" . $unique);
$zip->close();
As you can see I write a zip file in /tmp, at this point, I can open the file manually and it contains all files with the correct size.
But after I extract it to /final, for some reason some files are empty...
Any idea what could cause this?
You can do this way by throwing Exception at zip archive open time,
function DecompressFile()
{
$zip = new ZipArchive;
if ($zip->open('tmp/'.$name.'.zip') === TRUE) {
$zip->extractTo("final/" . $hwidDir);
$zip->close();
return 'completed';
}
else {
throw new Exception ("Decompress operation from ZIP file failed.");
}
}
As a part of my web application I want to upload file.
I want to protect his files with a Password. What I want to do is to take the uploaded file, zip it, and give the .zip file a password.
I know How to upload a file in laravel but I don't know how to zip it and set password. I'm using the below code to upload file.
$mobimg=$request->file('img');
$newfile2 = rand(456,987).time().$mobimg->getClientOriginalName();
$mobimg->move('images/upload', $newfile2);
$data=array(
'img' => $newfile2,
);
DB::table('file_upload')->insert($data);
I hope someone will help me do this
Thanks in advance.
You need at least PHP 7.2 to encrypt ZIP files with a password.
$zip = new ZipArchive();
$zipFile = __DIR__ . '/output.zip';
if (file_exists($zipFile)) {
unlink($zipFile);
}
$zipStatus = $zip->open($zipFile, ZipArchive::CREATE);
if ($zipStatus !== true) {
throw new RuntimeException(sprintf('Failed to create zip archive. (Status code: %s)', $zipStatus));
}
$password = 'top-secret';
if (!$zip->setPassword($password)) {
throw new RuntimeException('Set password failed');
}
// compress file
$fileName = __DIR__ . '/test.pdf';
$baseName = basename($fileName);
if (!$zip->addFile($fileName, $baseName)) {
throw new RuntimeException(sprintf('Add file failed: %s', $fileName));
}
// encrypt the file with AES-256
if (!$zip->setEncryptionName($baseName, ZipArchive::EM_AES_256)) {
throw new RuntimeException(sprintf('Set encryption failed: %s', $baseName));
}
$zip->close();
Problem
I am building an online file manager, for downloading a whole directory structure I am generating a zip file of all subdirectories and files (recursively), therefore I use the RecursiveDirectoryIterator.
It all works well, but empty directories are not in the generated zip file, although the dir is handled correctly. This is what i am currently using:
<?php
$dirlist = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
$filelist = new RecursiveIteratorIterator($dirlist, RecursiveIteratorIterator::SELF_FIRST);
$zip = new ZipArchive();
if ($zip->open($tmpName, ZipArchive::CREATE) !== TRUE) {
die();
}
foreach ($filelist as $key=>$value) {
$result = false;
if (is_dir($key)) {
$result = $zip->addEmptyDir($key);
//this message is correctly generated!
DeWorx_Logger::debug('added dir '.$key .'('.$this->clearRelativePath($key).')');
}
else {
$result = $zip->addFile($key, $key);
}
}
$zip->close();
If I ommit the FilesystemIterator::SKIP_DOTS I end up having a . file in all directories.
Conclusion
The iterator works, the addEmptyDir call gets executed (the result is checked too!) correctly, creating a zip file with various zip tools works with empty directories as intendet.
Is this a bug in phps ZipArchive (php.net lib or am I missing something? I don't want to end up creating dummy files just to keep the directory structure intact.