I need to be able to create an archive(zip) file with password protection using PHP. I am using Laravel 5.4 and PHP 7.1 version. I looked at this link here for ZipArchive class documentation in PHP. I also looked at here for setPassword function. But appears that creation of password protected archives is not supported. It will be a massive surprise for me if it is not possible to create password protected archive in a mature programming language such as PHP 7.1.
So I guess I must be missing something. Can someone point me to the right direction? E.g. a sample example or open source third party library or extension to achieve this will be greatly appreciated.
Easy peasy lemon squeezy (no).
Yes, creation of password protected archives is not supported (they will be created simply as non-protected archives, as you just described).
But, still it can be used to extract password protected archives.
Returning to the problem.
You always can just
<?php echo system('zip -P pass file.zip file.txt'); ?>
(this will work both on Windows and our beloved Linux)
But, if it not fits into your requirements, let's continue.
I would suggest you to use DotNetZip (Windows only), you will exactly dynamically generate AES-encrypted zip archives from PHP.
<?php
// origin: https://stackoverflow.com/a/670804/3684575
try
{
$fname = "zip-generated-from-php-" . date('Y-m-d-His') . ".zip";
$zipOutput = "c:\\temp\\" . $fname;
$zipfact = new COM("Ionic.Zip.ZipFile");
$zip->Name = $zipOutput;
$dirToZip= "c:\\temp\\psh";
# Encryption: 3 => 256-bit AES.
# 2 => 128-bit AES.
# 1 => PKZIP (Weak).
# 0 => None
$zip->Encryption = 3;
$zip->Password = "AES-Encryption-Is-Secure";
$zip->AddDirectory($dirToZip);
$zip->Save();
$zip->Dispose();
if (file_exists($zipOutput))
{
header('Cache-Control: no-cache, must-revalidate');
header('Content-Type: application/x-zip');
header('Content-Disposition: attachment; filename=' . $fname);
header('Content-Length: ' . filesize($zipOutput));
readfile($zipOutput);
unlink($zipOutput);
}
else
{
echo '<html>';
echo ' <head>';
echo ' <title>Calling DotNetZip from PHP through COM</title>';
echo ' <link rel="stylesheet" href="basic.css"/>';
echo ' </head>';
echo '<body>';
echo '<h2>Whoops!</h2>' . "<br/>\n";
echo '<p>The file was not successfully generated.</p>';
echo '</body>';
echo '</html>';
}
}
catch (Exception $e)
{
echo '<html>';
echo ' <head>';
echo ' <title>Calling DotNetZip from PHP through COM</title>';
echo ' <link rel="stylesheet" href="basic.css"/>';
echo ' </head>';
echo '<body>';
echo '<h2>Whoops!</h2>' . "<br/>\n";
echo '<p>The file was not successfully generated.</p>';
echo '<p>Caught exception: ', $e->getMessage(), '</p>', "\n";
echo '<pre>';
echo $e->getTraceAsString(), "\n";
echo '</pre>';
echo '</body>';
echo '</html>';
}
?>
But still, this is very dirty solution and more of that, not works on Linux.
So, although PHP is a mature language, there is no adequate method (excluding custom extension or something like that) to achieve such a simple task with pure PHP.
What you also can do, is to wait until PHP 7.2 will be available for production (cuz ZipArchive::setEncryptionName is implemented (thanks to Pierre and Remi)).
But, until then you also can try to port php_zip >= 1.14.0 to PHP < 7.2, but there is currently no compiled binaries available, so you have to compile it yourself and try if it is possible at all (I believe it is).
p.s. I would try it, but have no VS2015+ on my PC right now.
Related
I'm trying to echo a variable which is defined in Linux (Centos 6.3).
For accessing the server I use phpseclib 2.0.
When accessing using PuTTY (or similar), with vfrepc86 user, i'm getting the following output:
vfrepc86#illin935!:vfrepc86> echo $USER
vfrepc86
vfrepc86#illin935!:vfrepc86> pwd
/vfuser1/vfr/abp/vfrepc86
vfrepc86#illin935!:vfrepc86> echo $WL_HOME
/opt/weblogic1211_new/wlserver_12.1
When I try running the same with PHP (connecting with the same user vfrepc86), using the following code:
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib');
include('phpseclib/Net/SSH2.php');
$ssh = new Net_SSH2('illin935');
if (!$ssh->login('vfrepc86', '******')) {
exit('Login Failed');
}
echo "---User:---";
echo "<br>";
echo $ssh->exec('echo $USER');
echo "<br><br>";
echo "---Location of run:---";
echo "<br>";
echo $ssh->exec('pwd');
echo "<br><br>";
echo "---Default:---";
echo "<br>";
echo $ssh->exec('echo $WL_HOME'); //my first try, returns nothing
echo "<br><br>";
echo "---Using su:---";
echo "<br>";
echo $ssh->exec('su - vfrepc86 -c \'echo $PATH\''); //tried with su
echo "<br><br>";
echo "---Writing to file:---";
echo "<br>";
echo $ssh->exec('echo $WL_HOME >> temp.txt'); //tried writing to file
?>
I get the following:
---User:---
vfrepc86
---Location of run:---
/vfuser1/vfr/abp/vfrepc86
---Default:---
---Using su:---
standard in must be a tty
---Writing to file:---
You can see I'm not able to get the $WL_HOME. Though the script is running from the same path. As seen above, I've also tried using su but that returns standard in must be a tty. Printing the command to a file doesnt help, as the file gets empty.
NET_SSH2 does not request an interactive shell, so your .profile doesn't get executed. That's why $WM_HOME is not defined.
Instead of phpseclib, use the PECL ssh2 extension, it has a function ssh2_shell that requests an interactive shell.
Two solutions.
Enable a PTY ($ssh->enablePTY()) and then do $ssh->exec('command'). More info: http://phpseclib.sourceforge.net/ssh/pty.html
Use an interactive shell. eg. $ssh->read('[prompt]'); $ssh->write("command\n"); echo $ssh->read('[prompt]');. More info: http://phpseclib.sourceforge.net/ssh/examples.html#interactive
For example if I had the script:
<?php
$page = "My Page";
echo "<title>" . $page . "</title>";
require_once('header.php');
require_once('content.php');
require_once('footer.php');
?>
Is there something I can add to the bottom of that page to show the entire pre-compiled php?
I want to literally echo the php code, and not compile it.
So in my browser I would see the following in code form...
// stuff from main php
$page = "My Page";
echo "<title>" . $page . "</title>";
// stuff from require_once('header.php');
$hello = "Welcome to my site!";
$name = "Bob";
echo "<div>" . $hello . " " . $name . "</div>";
// stuff from require_once('content.php');
echo "<div>Some kool content!!!!!</div>";
// stuff from require_once('footer.php');
$footerbox = "<div>Footer</div>";
echo $footerbox;
Is this possible?
There's no way to do it native to PHP, but you could try to hack it if you just wanted something extremely simplistic and non-robust:
<?php
$php = file_get_contents($_GET['file']);
$php = preg_replace_callback('#^\s*(?:require|include)(?:_once)?\((["\'])(?P<file>[^\\1]+)\\1\);\s*$#m', function($matches) {
$contents = file_get_contents($matches['file']);
return preg_replace('#<\?php(.+?)(?:\?>)?#s', '\\1', $contents);
}, $php);
echo '<pre>', htmlentities($php), '</pre>';
Notes:
Warning: Allowing arbitrary file parsing like I've done with the fist line is a security hole. Do your own authentication, path restricting, etc.
This is not recursive (though it wouldn't take much more work to make it so), so it won't handle included files within other included files and so on.
The regex matching is not robust, and very simplistic.
The included files are assumed to be statically named, within strings. Things like include($foo); or include(__DIR__ . '/foo.php'); will not work.
Disclaimer: Essentially, to do this right, you need to actually parse the PHP code. I only offer the above because it was an interesting problem and I was bored.
echo '$page = "My Page";';
echo 'echo "<title>" . $page . "</title>";';
echo file_get_contents('header.php');
echo file_get_contents('content.php');
echo file_get_contents('footer.php');
For clarity I'd put the title generation in it's own file, then just use a series of echo file_get_contents()...
echo file_get_contents('title.php');
echo file_get_contents('header.php');
echo file_get_contents('content.php');
echo file_get_contents('footer.php');
I am on Ubuntu running Apache. The problem (not working) occurs on my production Strato webserver.
My PHP has gettext support, but it does not translate anything, although the strings are translated in the .mo file.
This is my code:
if (function_exists('bindtextdomain')) {
$domain = 'address_db';
echo putenv('LC_MESSAGES='.$lang);
echo '<br />';
echo setlocale(LC_MESSAGES, $lang);
echo '<br />';
$path = bindtextdomain($domain, "../locale/");
echo $path;
echo '<br />';
echo file_exists($path.'/'.$lang.'/LC_MESSAGES/'.$domain.'.mo') ? 'yes' : 'no';
echo '<br />';
echo bind_textdomain_codeset($domain, "iso-8859-1");
echo '<br />';
echo textdomain($domain);
echo '<br />';
$available_languages = array(
array('de_DE', _('German')),
array('en', _('English')),
array('nl', _('Dutch')),
array('tr', _('Turkish'))
);
echo _('Cancer');
}
The output is kind of promising:
1
/home/mu/Branches/address_db/locale
yes
iso-8859-1
address_db
Cancer
So it finds the file, but it still does not translate "Cancer".
What could that be?
Update
It works on my production server, but not on my testing server. Very strange …
Gettext translations are cached, you need to restart your server for it to pickup changes to .mo files.
It looks as if setlocale is returning false, it should return the new locale name if it worked correctly.
Is the value of $lang present in the output of locale -a? A common mistake is using e.g. de_DE rather than de_DE.utf8 or de_DE.iso88591 in your case.
I'm getting some fairly odd behavior here... I noticed that only localhost, a header statement I have worked just fine, but when copied over (SAME EXACT CODE) to my live site, the header statement no longer triggers.
I added some echos to help debug. This if statement will only trigger if the URL variable id is NOT set. So with this same exact code on localhost, I never see these debug statements. On the live site, I do... which I shouldn't. I should get redirected instead. Anyone know why a header statement would be ignored?
if((!isset($_GET['id'])) && $rows != 0) {
$result = mysql_query('SELECT videoinfo FROM videos where game_id=' . $gameid . ' LIMIT 1');
$row = mysql_fetch_array($result);
$tubeID = $row['videoinfo'];
echo '<script type="text/javascript">';
echo 'window.location = "videos.php?id=' . $tubeID . '&awayid=' . $awayid . '&homeid=' . $homeid . '&date=' . $date . '&time=' . $time . '&gameid=' . $gameid . '&play=0"';
echo '</script>';
}
EDIT 4 people have told me already that I can't have any echo calls before my header function. This code WORKS on localhost and the header function DOES trigger. Regardless, REMOVING the echo statements DOES NOT fix it.
AFAIK
Can't send header() after some echo.
You cannot output ANYTHING before you call header(), i.e. echo etc...
I don't think you can have a header after any sort of output. I just came up with that.
You need to enable output buffering. This is probably enabled on your localhost but not on your live system (or the value on the live system is too small).
This will keep your output buffered, and then the Header will work fine.
Your debug statements are making the problem worse.
header statements will not work if there is any output before they are called. In this case, your echos are killing it. Also, make sure there is no other output before this is called (white space, HTML, etc.).
at start of script, add
ob_start();
and just before calling header();, use
ob_clean();
ob_clean();
header('Location: videos.php?id=' . $tubeID . '&awayid=' . $awayid . '&homeid=' . $homeid . '&date=' . $date . '&time=' . $time . '&gameid=' . $gameid . '&play=0');
Edit
Check to ensure that your files are encoded correctly. For instance, if you are encoding in UTF-8, make sure you encode in UTF-8 without BOM (Byte Order Mark).
How to check depends on what you use to edit and save your file. For instance, I use Notepad++ so I just go to the 'Encoding' menu and select 'Encode in UTF-8 without BOM' and then save the file.
function goto_url($url) {
// must not have output anything prior to calling this function
if (!headers_sent()){
header('Location: '.$url); exit;
} else {
echo '<script type="text/javascript">';
echo 'window.location.href="'.$url.'";';
echo '</script>';
echo '<noscript>';
echo '<meta http-equiv="refresh" content="0;url='.$url.'" />';
echo '</noscript>'; exit;
};
};
http://www.w3schools.com/php/func_http_headers_sent.asp
Anyone knows how i can add a anchor to a web page that will force an Outlook Calendar file download? I need the file to open with outlook and the calendar info to be added to the user's calendar.
How can I create the MS outlook calendar files? Is there a standard/documented way I can create these calendar files using a script/automated way? (the script will be written in php)
thanks -
<?php
//This is the most important coding.
header("Content-Type: text/Calendar");
header("Content-Disposition: inline; filename=filename.ics");
echo "BEGIN:VCALENDAR\n";
echo "PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN\n";
echo "VERSION:2.0\n";
echo "METHOD:PUBLISH\n";
echo "X-MS-OLK-FORCEINSPECTOROPEN:TRUE\n";
echo "BEGIN:VEVENT\n";
echo "CLASS:PUBLIC\n";
echo "CREATED:20091109T101015Z\n";
echo "DESCRIPTION:How 2 Guru Event\\n\\n\\nEvent Page\\n\\nhttp://www.myhow2guru.com\n";
echo "DTEND:20091208T040000Z\n";
echo "DTSTAMP:20091109T093305Z\n";
echo "DTSTART:20091208T003000Z\n";
echo "LAST-MODIFIED:20091109T101015Z\n";
echo "LOCATION:Anywhere have internet\n";
echo "PRIORITY:5\n";
echo "SEQUENCE:0\n";
echo "SUMMARY;LANGUAGE=en-us:How2Guru Event\n";
echo "TRANSP:OPAQUE\n";
echo "UID:040000008200E00074C5B7101A82E008000000008062306C6261CA01000000000000000\n";
echo "X-MICROSOFT-CDO-BUSYSTATUS:BUSY\n";
echo "X-MICROSOFT-CDO-IMPORTANCE:1\n";
echo "X-MICROSOFT-DISALLOW-COUNTER:FALSE\n";
echo "X-MS-OLK-ALLOWEXTERNCHECK:TRUE\n";
echo "X-MS-OLK-AUTOFILLLOCATION:FALSE\n";
echo "X-MS-OLK-CONFTYPE:0\n";
//Here is to set the reminder for the event.
echo "BEGIN:VALARM\n";
echo "TRIGGER:-PT1440M\n";
echo "ACTION:DISPLAY\n";
echo "DESCRIPTION:Reminder\n";
echo "END:VALARM\n";
echo "END:VEVENT\n";
echo "END:VCALENDAR\n";
?>
Just in case someone needs it in PHP. I was searching found this.
Create an outlook .ics file
See here for more information. The example is in .NET, but it is simply writing output, so very easy to translate to PHP.