Can't use mv command with enough permissions using PHP - php

I am organizing my folders, the thing is I can't move my files due to permissions but when I checked, folder being created, files being moved and upper level folder is associated with same user and group apache:apache. I am also running this php code with apache user. What could be the problem?
Quick view;
exec('mv '.$path.$result->token.'-*.mp4 '.$path.getWeekNo($result->date).'/ 2>&1', $moveOut, $moveResult);
Code:
function processFilesByID($db, $path, $id, $type ='token')
{
$result = $db->get_row('SELECT id,token,title,date FROM DB_TABLE where id="' . $id . '";');
/* Debug - Start */
$db->debug();
// return "ID: " . $result->id . "<br />Token: " . $result->token . "<br />Title: " . $result->title . "<br />Date: " . $result->date;
/* Debug - End */
if (isset($result)) {
// Check if any file exists with given token command.
exec('ls -1 ' . $path . $result->token . '-* | wc -l', $out, $res);
// Check if noOfFile is greater than 0 and less than 10. Also check if command succeed.
if ($res == 0 && $out[0] > 0 && $out[0] < 10) {
// Move its media files [WHERE PROBLEM OCCURS]
exec('mv '.$path.$result->token.'-*.mp4 '.$path.getWeekNo($result->date).'/ 2>&1', $moveOut, $moveResult);
if($moveResult == 0){
// Double check if it's moved succesfully.
exec('ls -1 ' . $path.getWeekNo($result->date).'/'. $result->token . '-* | wc -l', $newOut, $newRes);
if ($newRes == 0 && $newOut[0] > 0 && $newOut[0] < 10) {
// Update DB with new path
if($db->query("UPDATE DB_TABLE SET token = '".getWeekNo($result->date).'/'.$result->token."' WHERE id= '".$result->id."'")){
}else{
}...
Output
Array
(
[0] => mv: cannot move '/###PATH###/+++FILE-NAME1+++' to '/###PATH###/16401c4a73848b7be4720d2e13a50a430c7b/+++FILE-NAME1+++': Permission denied
[1] => mv: cannot move '/###PATH###/+++FILE-NAME2+++' to '/###PATH###/16401c4a73848b7be4720d2e13a50a430c7b/+++FILE-NAME2+++': Permission denied
[2] => mv: cannot move '/###PATH###/+++FILE-NAME3+++' to '/###PATH###/16401c4a73848b7be4720d2e13a50a430c7b/+++FILE-NAME3+++': Permission denied
)
I also tried with php's built-in command but no luck so far.

Related

PHP in Windows: add an environment variable for User or Machine

I am trying to update the Path environment variable in Windows with a PHP script, but if I use putenv() it doesn't change. I can get the paths list in the Path variable but I am not able to update it.
Another problem is that if I use getenv('Path') to get the paths list, I have a unique string with all paths merged from the Path variable of User and of the Machine.
I'm wondering if there is a better way to do that, maybe acting directly in the registry key to update User Path variable.
UPDATE
I think I found out a half-solution, but it doesn't work as expected.
What do I want to do?
I just want to make a script that allow me to switch from a PHP version to another changing the Path variable.
I made the script, it seems to work and the Path variable is successfully updated, but even if I close and reopen the cmd prompt if I type php -v it doesn't seems to get the updated var. If I open the Environment Variables windows, then open the "Path" variable and click on Ok and Ok again, then the refresh is got but the cmd prompt.
This is very strange to me, and if I have to do this everytime, then script loose its benefit...
I recorded a video, I hope it explain the problem better than my English...
https://1drv.ms/v/s!Ao2s4w8xSxBSh7RY4y5pB8u1g_QFSQ
This is the code of the script:
// Load PHP available versions
$laragon_php_paths = 'D:\www-servers\laragon\bin\php';
$php_paths = scandir($laragon_php_paths);
$path_var_name = "Path";
// Backup before doing a disaster
$date = new DateTime();
exec('REG EXPORT HKCU\Environment BackupUserEnvironment_' . $date->format('YmdHisv') . '.reg');
// Load registry key of user's Path environment variable
exec('REG QUERY HKCU\Environment /v ' . $path_var_name, $output, $result);
$path = explode(' ', $output[2]);
$path_array = explode(';', $path[count($path) - 1]);
// Get the current PHP Version and get the key of the item of the PHP bin path
foreach ($path_array as $key => $path_item) {
if (strpos($path_item, $laragon_php_paths) !== false) {
$the_key = $key;
$current_php_version = substr($path_item, strrpos($path_item, '\\') + 1);
}
}
echo 'Available PHP versions:' . PHP_EOL . PHP_EOL;
$i = 0;
foreach ($php_paths as $dir) {
if ($dir === '.' || $dir === '..') continue;
echo ' [' . ++$i . '] ' . $dir;
if ($dir === $current_php_version) {
echo ' [Current version]';
}
echo PHP_EOL;
}
// Get file descriptor for stdin
echo PHP_EOL;
echo 'Select a PHP version: ';
$fd = fopen('php://stdin', 'r');
$choice = (int) fgets($fd);
echo PHP_EOL;
// Check if choice is between 1 and number of choices
if ($choice > 0 && $choice <= $i) {
// Change the original php version with the new one
$new_php_version = $php_paths[$choice + 1];
$path_array[$the_key] = $laragon_php_paths . '\\' . $new_php_version;
echo 'PHP version changed to: ' . $new_php_version . PHP_EOL;
} else {
echo 'No allowed choice, nothing changed.';
echo PHP_EOL;
}
// Escape some chars for cmd
$new_path_var = str_replace(['%', ' '], ['^%', '" "'], implode(';', $path_array));
$cmd = 'REG ADD HKCU\Environment /f /t REG_EXPAND_SZ /v ' . $path_var_name . ' /d ' . $new_path_var;
// Execute
exec($cmd);

How to use system command in php?

I am working on a PHP code as shown below in which conversion of mp4 into mp3 is happening at Line B.
I have added if block after system command to print Conversion Completed on the webpage once the conversion is complete but it doesn't seem to work.
Php code:
if (isset($_POST['id']))
{
for($i=0; $i <count($mp4_files); $i++) {
if($i == $_POST['id']) {
$f = $mp4_files[$i];
$parts = pathinfo($f);
switch ($parts['extension'])
{
case 'mp4' :
$filePath = $src_dir . DS . $f;
print_r($f); // Line A
system('ffmpeg -i ' . $filePath . ' -map 0:2 -ac 1 ' . $destination_dir . DS . $parts['filename'] . '.mp3', $result); // Line B
if($result)
{
echo "Conversion Completed";
}
}
}
}
}
Problem Statement:
I am wondering what changes I should make in the PHP code above so that once the conversion is complete; on the webpage, it should print Conversion Completed.
You can use shell_exec to get a return value and then put that in an if statement like this
$output = shell_exec('ffmpeg -i ' . $filePath . ' -map 0:2 -ac 1 ' . $destination_dir . DS . $parts['filename'] . '.mp3');
if ($output) {
echo "Conversion Completed!";
// or redirect here
}
Also, make sure to sanitize your inputs as they are exposed to a CLI interface.

shell_exec not working in php even after all the permissions

I have been trying to execute a shell script that executes a perl program and i am doing that using the shell_exec() in php.
I have given all the permissions to the folders as well as the executables. Also, shell_exec() is not disabled in the php.ini. I have even tried using the 2>&1 after the command. Kindly help.
Following is the code.
<?php
if(isset($_POST['EI']) && isset($_POST['OP']) && isset($_POST['GC']) && isset($_POST['PA']) && isset($_POST['HT']) && isset($_POST['AB'])) {
$data = 'Option entered by user :'.$_POST['OP'] . "\n" . 'The Threshold for GC is :'.$_POST['GC'] . "\n" . 'The Threshold for PA is :'.$_POST['PA'] . "\n" . 'The Threshold for HT is :'.$_POST['HT'] . "\n" . 'The Threshold for AB is :'.$_POST['AB'] . "\n" . 'The email id of the user is :'.$_POST['EI'] . "\n";
$ret = file_put_contents('/..path../out.txt', $data);
if($ret === false) {
die('There was an error writing this file');
} else {
echo "$ret bytes written to file";
}
} else {
die('no post data to process');
}
$output=shell_exec("./testing.sh");
?>

PHP LFTP data mirror output

I'm using a Linux local computer and need to backup/mirror some very large file structures regularly. I only have access to SFTP.
I was after a simple one click solution. I originally tried to write the little script in BASH but I've never used it before and am not up to scratch with the syntax so I resorted to PHP. (I do understand PHP is not designed for this kind of work, but I'm on a tight time scale and don't have the time to get into BASH atm)
<?php
//init
parse_str(implode('&', array_slice($argv, 1)), $_GET);
$error = array();
$lPrefix = '/home/hozza/Sites/';
$archiveLocation = '/home/hozza/Backups/';
$lDir = isset($_GET['l']) ? $_GET['l'] : $error[] = 'Local Directory Required';
$rDir = isset($_GET['r']) ? $_GET['r'] : $error[] = 'Remote Directory Required';
$bookmark = isset($_GET['b']) ? $_GET['b'] : $error[] = 'lftp Bookmark Required';
//Check for args
if(count($error) == 0) {
$archiveName = end(explode('/', $lDir)) . '_' . date('Y-m-d_H-i');
//Validate local dir
if(is_dir($lPrefix . $lDir)) {
//preserve Sublime Text 2 config SFTP files
$ST2_SFTP_conf = false;
if(file_exists($lPrefix . $lDir . '/sftp-config.json')) {
$ST2_SFTP_conf = file_get_contents($lPrefix . $lDir . '/sftp-config.json');
unlink($lPrefix . $lDir . '/sftp-config.json');
}
//Start mirror
$lftOutput = explode("\n", shell_exec('lftp -e "mirror -e -p --parallel=10 --log=' . $archiveLocation . 'logs/' . $archiveName . '.txt ' . $rDir . '/ ' . $lPrefix . $lDir . '/; exit top" ' . $bookmark));
//Tar regardless of lftp error or success
$tarOutput = shell_exec('cd ' . $lPrefix . ' && tar -czf ' . $archiveLocation . $archiveName . '.tar.gz ' . $lDir);
//Output completion or errors
shell_exec('notify-send -i gnome-network-properties -t 0 "Mirror & Archive Complete" "' . $archiveName . '\n\n' . implode('\n', $lftOutput) . $tarOutput . '"');
//put back ST2 SFTP conf
if($ST2_SFTP_conf != false) file_put_contents($lPrefix . $lDir . '/sftp-config.json', $ST2_SFTP_conf);
exit;
}
else shell_exec('notify-send -i error -t 0 "Mirror & Archive Error" "' . date('Y-m-d') . ' ' . date('H-i') . '\n' . $lDir . ' \n Does not exist! D:"');
}
else shell_exec('notify-send -i error -t 0 "Mirror & Archive Error" "' . date('Y-m-d') . ' ' . date('H-i') . '\n' . implode('\n', $error) . '"');
?>
It can be run for many sites via a short-cut like so...
terminator -T "Mirror & Archive" -e "php ~/Programs/mirror.php l=local-dir_path r=./ b=lftp-bookmark-name"
If no password is in the LFTP bookmark (there shouldn’t be as it's stored in plain text) the terminal prompts for a password, after the script has run, a nice notification is given with some info about files/folders/speed etc.
However, when the script is running in a terminal, only the "input password" bit is output to the terminal, I would like all the output displayed in the terminal (normally that would display what file/folder is currently working with etc.)
Anyone know how to do that?
IIRC the reason that you see the password prompt output to the terminal is that it is using stderr. You could try redirecting stdout to stderr for your commands which should show you the 'real-time' progress. Tack this on to the end of the shell_exec() command: 1>&2
ie:
shell_exec('lftp -e "mirror -e -p --parallel=10 --log=' . $archiveLocation . 'logs/' . $archiveName . '.txt ' . $rDir . '/ ' . $lPrefix . $lDir . '/; exit top" ' . $bookmark . ' 1>&2')
However, this will preclude you from having anything returned by shell_exec for logging purposes. What I would suggest is something like:
$log_stem = '/tmp/' . time() . '_'; // ie: /tmp/1357581737_
$lfOutfile = $log_stem . 'lftp.log';
$tarOutfile = $log_stem . 'tar.log';
shell_exec('lftp -blah | tee ' . $lfOutfile ' 1>&2' );
shell_exec('tar -blah | tee ' . $tarOutfile ' 1>&2' );
$lfOut = file_get_contents($lfOutfile);
$tarOut = file_get_contetns(tarOutfile);
// remove tmp files
unlink($lfOutfile);
unlink($tarOutfile);
Which will capture a copy of the output to a file before redirecting the output to stderr so you can watch it live.
However, if you want to run this via cron I would recommend against writing anything to stderr that is not an error, otherwise cron will send a warning email every time it is run.
I think the last answer was close:
Either this:
shell_exec('lftp -blah |& tee ' . $lfOutfile );
shell_exec('tar -blah |& tee ' . $tarOutfile );
Or if that still doesn't work try this:
shell_exec('lftp -blah 2>&1 | tee ' . $lfOutfile );
shell_exec('tar -blah 2>&1 | tee ' . $tarOutfile );

ftp_site() doesn't want to change CHMOD on the folders

I have a joomla page on which I want to install a few extensions. However due to the chmod permissions I am unable to upload and install the packages. Following the guide here I can see that in order for the plugins to be installed there are too many folders which permissions have to be changed.
For that I am creating a script which will iterate through each of the required folders and will change the permissions from 0775 to 0777.
<?php
// SET THE DESIRED CHMOD VALUE
if ($_GET['chmod']) {
$ftp_chmod = $_GET['chmod'];
}
else {
$ftp_chmod = "0755";
}
echo "chmod=" . $ftp_chmod . '<br />';
echo getcwd() . '<br />';
$currdir = getcwd(); // get current directory
// ESTABLISH AN FTP LOGIN SESSION
$ftp_server='example.com';
$ftp_user='username';
$ftp_pass='*****';
$conn_id = ftp_connect("$ftp_server");
if ( ftp_login($conn_id, $ftp_user, $ftp_pass) ) {
echo 'FTP CONNECTION IS SUCCESSFULL <br />';
}
else {
echo 'BAD CREDENTIALS';
exit();
}
// Define the folders for which the CHMODE will change the values
// There must be a leading space in front of the path in order for CHMOD to work
$folder_path = array(
' ' . $currdir . '/modules/',
' ' . $currdir . '/plugins/'
' ' . $currdir . '/tmp/',
' ' . $currdir . '/cache/'
);
echo '<br />';
foreach ( $folder_path as $key => $value )
{
$path = trim($value); // The leading space must be trimed fo is_dir() function to work
if ( is_dir($path) == true ) {
echo $path . ' -- ' . '<span style="color: #00B200">OK</span><br />';
echo 'CHMOD ' . $ftp_chmod . ' ' . $value . '<br />';
if (ftp_site($conn_id, 'CHMOD ' . $ftp_chmod . $value)) {
echo 'CHMOD ' . $ftp_chmod . ' IS <span style="color: #00B200">SUCCESSFULL</span><br /><br />';
}
else {
echo '<span style="color: crimson">CHMOD FAILED!</span><br /><br />';
}
}
else {
echo $path . ' -- ' . '<span style="color: crimson"><b>NOT EXIST</b></span><br />';
} // end if ( is_dir($path) == true ) else
} // end foreach ( $folder_path as $key => $value )
ftp_close($conn_id);
?>
Please note that the actual script is much larger due to the many folders that need to be changed. The folders shown in $folder_path = array() are just an example
When I execute the script on my server i get the folowind output:
chmod=0777
/var/www/example/data/www/example.com
FTP CONNECTION IS SUCCESSFULL
/var/www/example/data/www/example.com/modules/ -- OK
CHMOD 0777 /var/www/example/data/www/example.com/modules/
CHMOD FAILED!
/var/www/example/data/www/example.com/plugins/ -- OK
CHMOD 0777 /var/www/example/data/www/example.com/plugins/
CHMOD FAILED!
/var/www/example/data/www/example.com/tmp/ -- OK
CHMOD 0777 /var/www/example/data/www/example.com/tmp/
CHMOD FAILED!
/var/www/example/data/www/example.com/cache/ -- OK
CHMOD 0777 /var/www/example/data/www/example.com/cache/
CHMOD FAILED!
DOES ANYONE HAVE ANY IDEA ON HOW TO CHANGE THE CHMOD VALUE ON SO MANY FOLDERS?
UPDATE:
I also have to mention that I have tried to change the CHMOD value on each folder individually via FTP client and it is successfull. The problem comes when i have to change them through the script. The same acc with root privilege access is used from the FTP client and the script to change the files!
I have found a solution to the problem. What I did was a small modification to the foreach part of the script which made it work. Basically I just subtracted the required number of characters from the path returned from the getcwd() and that solved my problem.
Here is the change that i did:
---- REST OF THE SCRIPT OMITED -----
foreach ( $folder_path as $key => $value )
{
$path = trim($value); // The leading space must be trimed fo is_dis() function to work
if ( is_dir($path) == true ) {
$value_short = substr($value, 19); // <------------- Subtruct the required number od chars in order to create a relative path
echo $path . ' -- ' . '<span style="color: #00B200">OK</span><br />';
echo 'CHMOD ' . $ftp_chmod . ' ' . $value_short . '<br />';
if (ftp_site($conn_id, "CHMOD $ftp_chmod $value_short")) { // <-------------- Use the relative path in the function
echo 'CHMOD ' . $ftp_chmod . ' IS <span style="color: #00B200">SUCCESSFULL</span><br /><br />';
}
else {
echo '<span style="color: crimson">CHMOD FAILED!</span><br /><br />';
}
}
else {
echo $path . ' -- ' . '<span style="color: crimson"><b>NOT EXIST</b></span><br />';
} // end if ( is_dir($path) == true ) else
} // end foreach ( $folder_path as $key => $value )
---- REST OF THE SCRIPT OMITED -----
Did you try just enabling Joomla's FTP layer before installing components/plugins etc?

Categories