Escape PHP variable in sed command from Ruby script - php

I have a Ruby script that generates a sed command to replace some PHP code. The command is later executed via SSH.
command = "sed -i \"s*#{find_what}*#{replace_with}*\" #{file} "
The replace_with string will contain multiple lines of PHP code so the following escaping needs to take place:
command.gsub!(/\n/, '\\\n ') # Handle new-line escaping
command.gsub!(/&/, '\\\&') # Handle RegEx variable escaping
command.gsub!(/(\$[a-zA-Z0-9_]+)/) { |s| s.gsub!(/\$/, '\\$') } # Handle bash variable escaping
The command after escaping looks like this:
sed -i "s*require_once('file.php');*\n require_once(\$www_dir . \$path . '/file.php');\n *" /var/www/something.php
When executing this command manually everything works as expected. However if I execute the command via Kernel.system all the PHP variables are stripped out in the replacement string. Something.php ends up looking like this:
require_once( . . '/file.php');
Any ideas would be appreciated.
Thanks.

Update: try having single quotes around the sed command that way no bash variable substitution will be run. I'd try the ruby stuff out like this until it looks just right.
puts `echo #{command}`
If you're using SSH anyway, I'd just cook something up like this to be able to run it locally via ssh, makes it super easy to have total control by keeping it all ruby.
require 'net/sftp'
Net::SFTP.start('host', 'username', :password => 'password') do |sftp|
filedata = sftp.file.open("/path/to/remote", "r").read
filedata.gsub!(/foo/, "bar")
sftp.file.open("/path/to/remote", "w") do |f|
f.puts filedata
end
end
see http://net-ssh.rubyforge.org/sftp/v2/api/

Related

PHP: cannot run nested shell scripts

I hope you can help me.
I am dealing with a problem that I cannot solve. This is my issue. I am trying to exec a bash script through PHP. I tried with the method
exec()
with 3 arguments, arg1, arg2, and arg3.
php code
<?php exec("./randomScript.sh arg1 arg2 arg3"); ?>
randomScript.sh
.... # random code which exploits the three arguments -> executed normally..
.... # random code which exploits the three arguments -> executed normally..
./secondScript.sh $arg1 $arg2 $arg3 #<- this is the script that is not running (is not even started).
I have tried to change the permission (I've got full permission), change the way I call the randomScript.sh (through absolute path), but nothing occurred. Besides, I tried with:
shell_exec()
method, but nothing changed. Of course, if I run the secondScript.sh via terminal everything works fine.
I cannot understand which is the problem. Could you please help me?
Thanks in advance.
In the inner shell, the arguments are not called like that (because it is invoked by the shell, not by PHP).
./secondScript.sh "$1" "$2" "$3"
or just
./secondScript.sh $*
At this stage, just remember that spaces, quotes, and dollar signs in the arguments you pass must be avoided at all costs (the solution is escaping them, but how to do it exactly is tricky).
You also might want to do instead:
$ret = shell_exec("./randomScript.sh 'arg1' 'arg2' 'arg3' 2>&1");
so that in $ret you might find error messages and output from the inner shell.
You should escape your string command before passing it in exec function, i think it may help you
Escapeshellcmd()
...
$escaped_command = escapeshellcmd("./randomScript.sh arg1 arg2 arg3");
exec($escaped_command);
...
Escapeshellarg()
For system command, i recommand using system
...
$escaped_command = escapeshellarg("./randomScript.sh arg1 arg2 arg3");
system($escaped_command);
...
You also need to make sure that your PHP code does not change working dir, and both shell scripts have execute permissions, and filesystems allows to exec files on it.
I would avoid exec("./script $arg ...");, I would rather specify the interpreter to use and full path to the script like exec("sh /home/user/project/script.sh $arg ...");

Usage of quotes in PHP shell_exec() command

I have come across an interesting situation with the shell_exec() function in PHP. This command works:
$res = shell_exec("mdb-export -D \"%d/%m/%y\" ".$this->mdbFileName." ".$tableName." &> " . $outputFile);
However, this command does not work:
$res = shell_exec("mdb-export -D \"%d/%m/%y\" ".$this->mdbFileName." \"".$tableName."\" &> " . $outputFile);
When entering the command in a shell (either way - with or without quotes around the table name) it works fine. I would really like to know why the first set of escaped quotes does not affect shell_exec():
\"%d/%m/%y\"
But the second set:
\"".$tableName."\"
Does not allow shell_exec to execute. FYI: all file name variables in the script are full file paths. They were entered in the exact same way when testing in the shell. Any thoughts?
EDIT: Upon failure, shell_exec returns NULL and the command is not executed.
After some more testing, it appears that the $tableName variable contained an extra space. Another part of the program was pulling the table name from the MDB file and left a trailing space.
When echoing out the $tableName variable everything appeared fine because the space was invisible. When running shell_exec without quotes surrounding the table name, the command executed because no errors occur if there are extra spaces between parameters. However, when surrounding the variable with quotes, the mdb-export program started looking for:
"tableName "
instead of
"tableName"
causing a silent, yet complete failure.

Jenkins - parametrise .php file

I am configuring Jenkins in order to make it build my project.
It checks out source code, installs all required libs etc..
My application configuration is stored in params.php file (Yii 1.x style), it looks the following way:
return array(
'dbHost' => 'dbHostValuePlaceholder',
'dbPasssword' => 'dbPasswordValuePlaceholder',
/* other values go here */
);
Obviously I need to replace dbPasswordValuePlaceholder with password that I set when starting parametrised build.
Current solution I've found is running this as shell command:
sed -i s/dbPasswordValuePlaceholder/$DB_PASSWORD/g $WORKSPACE/protected/config/params.php
where $DB_PASSWORD is corresponding variable.
This solution work perfectly with simple strings, but password may look like a1#2";$&^*&-=+/*-:'/.,,,,,,,,^^^^^ - in this case sed fails because of unescaped characters.
I have searched for different Jenkins plugins, but there are only plugins that work with other formats like .xml etc, and neither works with .php files.
I need to avoid moving my config values out of .php file to some other format.
Is there a way to replace the described tokens in .php file with build parameters values ?
UPDATE
As #Stanjer recommended, I have tried to set param value to:
a1#2";$&^*&-=+/*-:\'/.,,,,,,,,^^^^^
So, in this case, the following code in PHP would be right, valid:
'universalPassword' => 'a1#2";$&^*&-=+/*-:\'/.,,,,,,,,^^^^^',
It does not help, here is output:
[build.int] $ /bin/sh -xe /tmp/hudson642312569695847678.sh
+ sed -i s/defaultUniversalPassword/a1#2";$&^*&-=+/*-:\'/.,,,,,,,,^^^^^/g /var/www/build.int/protected/config/params.php
sed: -e expression #1, char 43: unknown option to `s'
Build step 'Execute shell' marked build as failure
Finished: FAILURE
Thanks for the updated question.
In your case you should show that it's already escaped by providing it as $'string'.
So the command will look like:
$ sed s#dbPasswordValuePlaceholder#$'"a1#2";$&^*&-=+/*-:\'/.,,,^^^"'#g test.php
and output will be:
<?php
return array(
'dbHost' => 'dbHostValuePlaceholder',
'dbPassword' => '"a1#2";$dbPasswordValuePlaceholder^*dbPasswordValuePlaceholder-=+/*-:'/.,,,,,,,,^^^^^"',
/* other values go here */
);
?>
If using with variable:
export NEWPASS=$'"a1#2";$&^*&-=+/*-:\'/.,,,^^^"'
sed "s#dbPasswordValuePlaceholder#$NEWPASS#g" test.php
I am not sure about any jenkins plugin which works that way , but I needed to know if its possible to make sed ignore the special characters using this :
sed with special characters
And I suppose you must be using a Password Parameter with your parameterized job, which hides the password.

Using PHP to execute cmd commands

How do I properly execute commands in the command line using php? For example I'm using the command below in the command line to convert a docx file into a pdf file:
pdfcreator.exe /PF"D:\Documents\sample.docx
Now using PHP code I want to be able to execute the same command but nothing seems to be happening:
<?php
shell_exec('pdfcreator.exe /PF"D:\Documents\sample.docx"');
?>
Is this possible in PHP?If yes, how do I do it?
system("c:\\path\\to\\pdfcreator.exe /PF\"D:\\Documents\\sample.docx"");
try this.
Don't forget to escape your command with escapeshellcmd(). This will prevent you from having to use ugly backslashes and escape characters.
There are also other alternatives which may work:
`command` // back ticks drop you out of PHP mode into shell
exec('command', $output); // exec will allow you to capture the return of a command as reference
shell_exec('command'); // will return the output to a variable
system(); //as seen above.
Also, make sure your .exe is included within your $PATH variable. If not, include the full path for the command.

How do I to properly handle spaces in PHP Shell_exec?

I'm running on win2003 server, PHP 526, via the cmd-line.
I have a cmdline string:
$cmd = ' "d:\Prog Files\foo.exe" -p "d:\data path\datadir" ';
Trying to do this in php code
$out = `$cmd`; # note use of backticks AKA shell_exec
results in a failure by foo.exe as it interprets the -p arg as "d:\data".
However, the same $cdm string copied to the windows shell cmdline executes successfully.
How do I properly handle spaces in PHP shell_exec?
Use escapeshellarg() to escape your arguments, it should escape it with an appropriate combination of quotation marks and escaped spaces for your platform (I'm guessing you're on Windows).
Unlike Unix, which requires quotes within quotes to be escaped, Windows doesn't seem to work this way. How it keeps track of the quotes is beyond me, but this actually seems to work, despite all logic to the contrary:
$cmd = '" "C:\Path\To\Command" "Arg1" "Arg2" "';
$fp = popen($cmd, 'r');
$output='';
while ($l = fgets($fp, 1024))
$output.=$l;
I'm guessing command.exe is taking the command string total and nixing the (otherwise redundant) outside quotes. Without these outside quotes, DOS does some weird things. This solution is similar to post by user187383, but does away with the "cmd /c" which only obfuscates what's actually happening along with a mild performance cut, since cmd /c is implicit by the shell call in the first place!
This is an interesting problem. Apparently, PHP lets you put double quotes around the program or the arguments, but not both. It may be worth reporting this as a bug.
A work around is to use the DOS 8.3 name instead of quotes. E.g., "C:\Program Files\" usually becomes "C:\Progra~1".
Had this problem too - came up with an idea to route the launching through cmd.exe. The trick here is not to get lost in the double qoutes. Generally you want to put anything you want to run in:
exec('cmd /c " '.$path.' "';
Where $path is a already double-quoted path to your executable. Example:
$path = '"C:\Program Files\ToDoList Simple\ToDoList.exe" "C:\SomePath\todo.tdl" -nt test -cm test2';

Categories