Unzipping to a variable - php

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.

Related

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.

Can PHP decompress a taz file? (.tar.Z)

I have tried to use Zlib to decompress the file, but it just said "Data error" and gave me an empty file.
This is the code I tried:
// Open a new temp file to write new file to
$tempFile = fopen("tempFile", "w");
// Make sure tempFile is empty
ftruncate($tempFile, 0);
// Write new decompressed file
fwrite($tempFile, zlib_decode(file_get_contents($path))); // $path = absolute path to data.tar.Z
// close temp file
fclose($tempFile);
I have also tried to decompress it in parts, going from .tar.Z to .tar to just a file. I tried using lzw functions to take off the .Z, but I was unable to make it work. Is there a way to do this?
EDIT:
Here is some more code I have tried. Just to make sure the file_get_contents was working. I still get a "data error".
$tempFile = fopen("tempFile.tar", "w");
// Make sure tempFile is empty
ftruncate($tempFile, 0);
// Write new decompressed file
$contents = file_get_contents($path);
if ($contents) {
fwrite($tempFile, gzuncompress($contents));
}
// close temp file
fclose($tempFile);
EDIT2: I think the reason why LZW was not working is because the contents of the .tar.Z file looks like this:
��3dЀ��0p���a�
H�H��ŋ3j��#�6l�
The LZW functions I have tried both use ASCII characters in their dictionaries. What kind of characters are these?
So you want to decompress a taz file natively with PHP? Give my new extension a try!
lzw_decompress_file('3240_05_1948-1998.tar.Z', '3240_05_1948-1998.tar');
$archive = new PharData('/tmp/3240_05_1948-1998.tar');
mkdir('unpacked');
$archive->extractTo('unpacked');
Also note, the reason the zlib functions aren't working is because you need LZW compression, not gzip compression.
according to this url https://kb.iu.edu/d/acsy you can try
<?php
$file = '/tmp/archive.z';
shell_exec("uncompress $file");
if you don't have Unix like OS check https://kb.iu.edu/d/abck for appropriate program.
The file is compressed with LZW compression, and I tried a few but there seems to be no reliable method for decompressing these in PHP. Cosmin's answer contains the correct first step but after using your system's uncompress utility to decompress the file, you still have to extract the TAR file. This can be done with PHP's built-in tools for handling its custom PHAR files.
// the file we're getting
$url = "ftp://ftp.ncdc.noaa.gov/pub/data/hourly_precip-3240/05/3240_05_2011-2011.tar.Z";
// where to save it
$output_dir = ".";
// get a temporary file name
$tempfile = sys_get_temp_dir() . basename($url);
// get the file
$compressed_data = file_get_contents($url);
if (empty($compressed_data)) {
echo "error getting $url";
exit;
}
// save it to a local file
$result = file_put_contents($tempfile, $compressed_data);
if (!$result) {
echo "error saving data to $tempfile";
exit;
}
// run the system uncompress utility
exec("/usr/bin/env uncompress $tempfile", $foo, $return);
if ($return == 0) {
// uncompress strips the .Z off the filename
$tempfile = preg_replace("/.Z$/", "", $tempfile);
// remove .tar from the filename for use as a directory
$tempdir = preg_replace("/.tar$/", "", basename($tempfile));
try {
// extract the tar file
$tarchive = new PharData($tempfile);
$tarchive->extractTo("$output_dir/$tempdir");
// loop through the files
$dir = new DirectoryIterator($tempdir);
foreach ($dir as $file) {
if (!$file->isDot()) {
echo $file->getFileName() . "\n";
}
}
} catch (Exception $e) {
echo "Caught exception untarring: " . $e->getMessage();
exit;
}
} else {
echo "uncompress returned error code $return";
exit;
}
Please try this.
<?php
try {
$phar = new PharData('myphar.tar');
$phar->extractTo('/full/path'); // extract all files
$phar->extractTo('/another/path', 'file.txt'); // extract only file.txt
$phar->extractTo('/this/path',
array('file1.txt', 'file2.txt')); // extract 2 files only
$phar->extractTo('/third/path', null, true); // extract all files, and overwrite
} catch (Exception $e) {
// handle errors
}
?>
Source : http://php.net/manual/en/phardata.extractto.php
I haven't tested it but i hope it will work for you.

How to extract bz2 file in php

I have exported an SQL file from a database by using phpmyadmin. The file is named final.sql.bz2 and then I uploaded it onto my Live Server.
The question is, how could I extract that file by using PHP code? I tried to search for that on google, but not getting any result. How could I unzip it?
You should use the bzip function from PHP not the zip functions they are different.
http://php.net/manual/en/book.bzip2.php
Or if its possible you can use exec to execute the bunzip2 command to extract your file from your archive:
bunzip2 [DATEI].bz2
I needed to extract bz2 in shared hosting where tar couldnt help me to extract (got error with bzip2 and lbzip2, and I could not install anything or do sudo...)
I solved it by creating a php file and run it from command line (of course you can modify the script to use it online too).
bunzip2.php
<?php
function decompress($data)
{
// Decompress the file
if (#file_exists($data)) {
$bz = bzopen($data, 'r');
$uncompressed = '';
// Read the uncompressed data.
while (!feof($bz)) {
$uncompressed .= bzread($bz, 4096);
}
// Close the Bzip2 compressed file and write
// the data to the uncompressed file.
bzclose($bz);
if (stripos($data, '.tbz2') !== false) {
$newFile = str_replace('.tbz2', '.tar', $data);
} else {
if (stripos($data, '.tbz') !== false) {
$newFile = str_replace('.tbz', '.tar', $data);
} else {
$newFile = str_replace('.bz2', '', $data);
}
}
file_put_contents($newFile, $uncompressed);
return $newFile;
// Else, decompress the string
} else {
return bzdecompress($data);
}
}
decompress($argv[1]);
?>
php bunzip2.php my.tar.bz2
(I just searched for bz2+php on github, I did not check the code in detail but it does the work ;)

Unable to copy image from URL in PHP with upload class

I'm trying to make a upload class with PHP. so this is my first PHP class:
//Create Class
class Upload{
//Remote Image Upload
function Remote($Image){
$Content = file_get_contents($Image);
if(copy($Content, '/test/sdfsdfd.jpg')){
return "UPLOADED";
}else{
return "ERROR";
}
}
}
and usage:
$Upload = new Upload();
echo $Upload->Remote('https://www.gstatic.com/webp/gallery/4.sm.jpg');
problem is, this class is not working. where is the problem? I'm new with PHP classes and trying to learn it.
thank you.
copy expects filesystem paths, e.g.
copy('/path/to/source', '/path/to/destination');
You're passing in the literal image you fetched, so it's going to be
copy('massive pile of binary garbage that will be treated as a filename', '/path/to/destination');
You want
file_put_contents('/test/sdfsdfg.jpg', $Content);
instead.
PHP's copy() function is used for copying files that you have permission to copy.
Since you're getting the contents of the file first, you could use fwrite().
<?php
//Remote Image Upload
function Remote($Image){
$Content = file_get_contents($Image);
// Create the file
if (!$fp = fopen('img.png', 'w')) {
echo "Failed to create image file.";
}
// Add the contents
if (fwrite($fp, $Content) === false) {
echo "Failed to write image file contents.";
}
fclose($fp);
}
Since you want to download a image, you could also use the imagejpeg-method of php to ensure you do not end up with any corrupted file format afterwards (http://de2.php.net/manual/en/function.imagejpeg.php):
download the target as "String"
create a image resource out of it.
save it as jpeg, using the proper method:
inside your method:
$content = file_get_contents($Image);
$img = imagecreatefromstring($content);
return imagejpeg($img, "Path/to/targetFile");
In order to have file_get_contents working correctly you need to ensure that allow_url_fopen is set to 1 in your php ini: http://php.net/manual/en/filesystem.configuration.php
Most managed hosters disable this by default. Either contact the support therefore or if they will not enable allow_url_fopen, you need to use another attempt, for example using cURL for file download. http://php.net/manual/en/book.curl.php
U can use the following snippet to check whether its enabled or not:
if ( ini_get('allow_url_fopen') ) {
echo "Enabled";
} else{
echo "Disabled";
}
What you describe is more download (to the server) then upload. stream_copy_to_stream.
class Remote
{
public static function download($in, $out)
{
$src = fopen($in, "r");
if (!$src) {
return 0;
}
$dest = fopen($out, "w");
if (!$dest) {
return 0;
}
$bytes = stream_copy_to_stream($src, $dest);
fclose($src); fclose($dest);
return $bytes;
}
}
$remote = 'https://www.gstatic.com/webp/gallery/4.sm.jpg';
$local = __DIR__ . '/test/sdfsdfd.jpg';
echo (Remote::download($remote, $local) > 0 ? "OK" : "ERROR");

Unzip php files

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.

Categories