Unzip php files - php

I'm trying to extract a zip file witch contains php files.
Taking for example a zip name 'test.zip' and inside, a zip.php file with this code:
<?php
class php{
}
?>
I've tried with two differents snippets to extract the zipe file:
$zip = zip_open ( 'test.zip' );
while($file = zip_read($zip)){
$archivo = (zip_entry_name($file));
zip_entry_open($zip, $file);
$contenido = zip_entry_read($file);
$fopen = fopen($archivo,'w+');
fwrite($fopen, $contenido);
}
<?php
$zip = new ZipArchive;
$res = $zip->open('test.zip');
if ($res === TRUE) {
$zip->extractTo('./');
$zip->close();
echo 'ok!';
} else {
echo 'ko!';
}
?>
But in both cases, the result is always the same:
<?php
class phpclass{
function clase(){
}
}
?>
The file extracted is twice longer, and has twice of empty breaklines than original.
Is there anyway to extract an identical copy of files contained in the zip file?

Please replace this:
$fopen = fopen($archivo,'w+');
... with this:
$fopen = fopen($archivo,'w+b');
The b flag stands for "binary" and disables line feed conversion. Flags are described in the fopen() manual page.

Related

Can't unzip file with php

I have a folder in my web server were I put zip files that I need to then unzip. I want to do that with php and this is what I have tried but it does not work:
<?php
$file = $_GET["file"];
$zip = new ZipArchive;
$res = $zip->open($file+'.zip');
$zip->extractTo('./');
$zip->close();
?>
The zip files are in the same folder as the php file, but when I go to the php page it does nothing.
By doing some testing I have found out that the script dies on the $zip = new ZipArchive; line
How can I manage this to work?
<?php
$fileName = $_GET['file']; // get file name in the URL param "file"
if (isset($fileName)) { // if $fileName php variable is set than
$zip = new ZipArchive; // create object
$res = $zip->open($fileName); // open archive
if ($res === TRUE) {
$zip->extractTo('./'); // extract contents to destination directory
$zip->close(); //close the archieve
echo 'Extracted file "'.$fileName.'"';
} else {
echo 'Cannot find the file name "'.$fileName.'" (the file name should include extension (.zip, ...))';
}
}
else {
echo 'Please set file name in the "file" param';
}
?>
Note:- For More Details Please refer https://www.php.net/manual/en/class.ziparchive.php
I have found the problem.
The code is fine, but the hosting service is not, and they do not have the ZIP extension available right now
Try this code. Also change $zip->open($file+".zip"); to $zip->open($file);.
+ (plus sign) is not concatenation operator in php
<?php
// $_GET["file"] is set to `a.zip`
$file = $_GET["file"];
$zip = new ZipArchive;
$res = $zip->open($file);
$zip->extractTo('./');
$zip->close();
?>

How to save extracted zip file with specific filename

I have zip files with only one file inside it, but it has new name every time. I need to extract file and save it with specific file name, not extracted one.
$zip = new ZipArchive;
$res = $zip->open($tmp_name);
if ($res === TRUE) {
$path = _PATH."/files/";
$zip->extractTo($path);
$zip->close();
echo 'Unzip!';
}
Abowe code works, but I need to have specific filename. For example anyfile located under zip (eg. pricelist025.xml should be named temp.xml
Rename your specific file before you extract it.
$zip = new ZipArchive;
$res = $zip->open($tmp_name);
if ($res === TRUE) {
$zip->renameName('pricelist025.xml','temp.xml');
$path = _PATH."/files/";
$zip->extractTo($path);
$zip->close();
echo 'Unzip!';
} else {
echo 'failed, code:' . $res;
}
I hope this works.
UPDATE 1
There is two options if you want to change the file names.
1. change the file names before extracting -This way zip files will be modified
2. change the file names after extracting -Zip files will remain as they were before
Changing file names before extracting
We have to define a pattern for filenames. Here, Files will be in this patter : myfile0.xml, myfile1.html, adn so on..
Note: extension will be preserved.
$zip = new ZipArchive;
$res = $zip->open('hello.zip');
$newfilename = 'myfile';
for($i=0;$i<$zip->count();$i++)
{
$extension = pathinfo($zip->getNameIndex($i))['extension'];
$zip->renameName($zip->getNameIndex($i), $newfilename.$i.'.'.$extension);
}
Chaning file names after extracting
File names will in the same pattern as above.
$directory = 'hello/'; //your extracted directory
$newfilename = 'myfile';
foreach (glob($directory."*.*") as $index=>$filename) {
$basename = pathinfo($filename)['basename'];
if(!preg_match('/myfile\d\./', $basename)) {
$extension = pathinfo($filename)['extension'];
rename($filename,$newfilename.$index.'.'.$extension);
}
}
What we are here scanning the all the files from the extracted directory for which doesn't have a filename in the patter myfile[num]. and then we are changing it's name.
UPDATE 2
I just noticed you have updated your question.
As you have just one file and you want to extract it every time with different name. You should rename it every time you extract.
$zip = new ZipArchive;
$newfilename = "myfile".rand(1,999); //you can define any safe pattern here that suites you
if($zip->open('help.zip')===TRUE)
{
$path = '/your/path/to/directory';
$filename = $zip->getNameIndex(0);
if($zip->extractTo($path))
{
echo "Extracted";
}else{
echo "Extraction Failed";
exit();
}
$extension = pathinfo($filename)['extension'];
rename($path."/$filename",$path."/$newfilename".'.'.$extension);
echo "Extracted with different name successfully!";
} else {
echo "Failed";
}

Create a zip archive with a password

So, I creating a zip file with a password:
function createZip($fileName,$fileText,$zipFileName,$zipPassword)
{
shell_exec('zip -P '.$zipPassword.' '.$zipFileName.'.zip '.$fileName);
unlink($fileName);
return file_exists($zipFileName.'.zip');
}
$filex = "/backup/home/fyewhzjp/long_location_of_a_file/temp/data/map10/data.txt";
// $file_content = 'test';
$archive = "/backup/home/fyewhzjp/long_location_of_a_file/temp/data/map10/archive";
createZip($filex,$file_content,$archive,$pass);
And it works. I'm getting a archive.zip in my /temp/data/map folder on the website. But, when I open my archive I can see a bunch of folders, and data.txt at the end, let's say it will be
/backup/home/fyewhzjp/long_location_of_a_file/temp/data/map10/data.txt
So, I need to leave only data.txt in my folder, without other folders. How can I do it?
If anyone will face the same problem as I did, here is the solution:
Just add -jrq after zip in shell_exec like this:
shell_exec('zip -jrq -P '.$zipPassword.' '.$zipFileName.'.zip '.$fileName);
After that, full path will be ignored.
In addition to #Script47...
Pure PHP Available as of PHP 7.2.0 and PECL zip 1.14.0, respectively, if built against libzip ≥ 1.2.0.
<?php
$zip = new ZipArchive;
$res = $zip->open('test.zip', ZipArchive::CREATE);
if ($res === TRUE) {
// Add files
$zip->addFromString('test.txt', 'file content goes here');
$zip->addFile('data.txt', 'entryname.txt');
// Set global (for each file) password
$zip->setPassword('your_password_here');
// This part will set that 'data.txt' will be encrypted with your password
$zip->setEncryptionName('data.txt', ZipArchive::EM_AES_128); // Have to encrypt each file in zip
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
?>
Rather than using shell_exec why don't you just use the ZipArchive class with the functions ZipArchiveOpen::open and ZipArchive::setPassword, it seems that that would make things a lot easier.
<?php
$zip = new ZipArchive;
$res = $zip->open('test.zip', ZipArchive::CREATE);
if ($res === TRUE) {
$zip->addFromString('test.txt', 'file content goes here');
$zip->addFile('data.txt', 'entryname.txt');
$zip->setPassword('your_password_here');
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
?>
Note:
This function only sets the password to be used to decompress the archive; it does not turn a non-password-protected ZipArchive into a password-protected ZipArchive.

Unzipping to a variable

I need to process the contents of a zipped file, but I can't change the permissions on the server where my program will be hosted.
This means that I can't download the zip file to the server, so I need to read the contents of the file into a variable without writing it to the file system.
Can I grab the string contents of such variable and get the unzipped contents into a new variable?
So far, I've looked into using the zip php extension, and the pclzip library, but both need to use actual files.
This is what I want to do in pseudo code:
$contentsOfMyZipFile = ZipFileToString();
$myUnzippedContents = libUnzip($contentsOfMyZipFile);
Any ideas?
Look at this example.
<?php
$open = zip_open($file);
if (is_numeric($open)) {
echo "Zip Open Error #: $open";
} else {
while($zip = zip_read($open)) {
zip_entry_open($zip);
$text = zip_entry_read($zip , zip_entry_filesize($zip));
zip_entry_close($zip);
}
print_r($text);
?>
I use this in my project:
function unzip_file( $data ) {
//save in tmp zip data
$zipname = "/tmp/file_xxx.zip";
$handle = fopen($zipname, "w");
fwrite($handle, $data);
fclose($handle);
//then open and read it.
$open = zip_open($zipname);
if (is_numeric($open)) {
echo "Zip Open Error #: $open";
} else {
while ($zip = zip_read($open)) {
zip_entry_open($zip);
$text = zip_entry_read($zip, zip_entry_filesize($zip));
zip_entry_close($zip);
}
}
/*delete tmp file and return variable with data(in this case plaintext)*/
unlink($zipname);
return $text;
}
I hope it helps you.

PHP Word File line counter

I need to make a PHP function that will count the number of lines in a Word File (.doc, docx)
This code does not seem to work correctly for me :
$name = 'test.doc';
$line_count = count(file($name));
echo $line_count
My guess is that this script does not work well with .doc or .docx but works good in .txt files. Are there any alternatives available out there? Tnx!
Only .docx can be opened with simple PHP as it is a zip file:
$zip = new ZipArchive;
if ($zip->open('test.docx') === TRUE) {
$xml = $zip->getFromName('docProps/app.xml');
$zip->close();
} else {
$xml = false;
}
if($xml){
$xml = simplexml_load_string($xml);
echo $xml->Lines;
}

Categories