PHP exec change encoding - php

I need to address UTF-8 filenames with the php exec command. The problem is that the php exec command does not seem to understand utf-8. I use something like this:
echo exec('locale charmap');
returns ANSI_X3.4-1968
looking at this SO question, the solution lookes like that:
echo exec('LANG=de_DE.utf8; locale charmap');
But I still get the same output: ANSI_X3.4-1968
On the other hand - if I execute this php command on the bash command line:
php -r "echo exec('LANG=de_DE.UTF8 locale charmap');"
The output is UTF-8.
So the questions are:
Why is there an different result be executing the php command at bash and at apache_module/web page?
How to set UTF-8 for exec if it runs inside a website as apache module?

To answer my own question - i found the following solution:
setting the locale environment variable with PHP
$locale='de_DE.UTF-8';
setlocale(LC_ALL,$locale);
putenv('LC_ALL='.$locale);
echo exec('locale charmap');
This sets to / returns UTF-8. So i'm able to pass special characters and umlauts to linux shell commands.

This solves it for me (source: this comment here):
<?php
putenv('LANG=en_US.UTF-8');
$command = escapeshellcmd('python3 myscript.py');
$output = shell_exec($command);
echo $output;
?>

I had the similar problem. My program was returning me some German letters like: üäöß. Here is my code:
$programResult = shell_exec('my script');
Variable $programResult is containing German umlauts, but they were badly encoded. In order to encode it properly you can call utf8_encode() function.
$programResult = shell_exec('my script');
$programResult = utf8_encode($programResult);

Related

How can you use the "*" path wildcard via PHP exec() as part of a `cp` or `ls` command?

I just cannot fathom how to get the PHP exec() or shell_exec() functions to treat a '*' character as a wildcard. Is there some way to properly encode / escape this character so it makes it through to the shell?
This is on windows (via CLI shell script if that matters, Terminal or a git-bash yields the same results).
Take the following scenario:
C:\temp\ contains a bunch of png images.
echo exec('ls C:\temp\*');
// output: ls: cannot access 'C:\temp\*': No such file or directory
Permissions is not the problem:
echo exec('ls C:\temp\exmaple.png');
// output: C:\temp\example.png
Therefore the * character is the problem and is being treated as a literal filename rather than a wildcard. The file named * does not exist, so from that point of view, it's not wrong...
It also does not matter if I use double quotes to encase the command:
echo exec("ls C:\temp\*");
// output: ls: cannot access 'C:\temp\*': No such file or directory
I have also tried other things like:
exec(escapeshellcmd('ls C:\temp\*'));
exec('ls C:\temp\\\*');
exec('ls "C:\temp\*"');
exec('ls "C:\temp\"*');
And nothing works...
I'm pretty confused that I cannot find any other posts discussing this but maybe I'm just missing it. At this point I have already worked around the issue by manually programming a glob loop and using the internal copy() function on each file individually, but it's really bugging me that I do not understand how to make the wildcard work via shell command.
EDIT:
Thanks to #0stone0 - The answer provided did not particularly answer my initial question but I had not tried using forward slashes in the path and when I do:
exec('ls C:/temp/*')
It works correctly, and as 0stone0 said, it only returns the last line of the output, which is fine since this was just for proof of concept as I was not actually attempting to parse the output.
Also, on a side note, since posting this question my system had been updated to Win11 22H2 and now for some reason the original test code (with the backslashes) no longer returns the "Cannot access / no file" error message. Instead it just returns an empty string and has no output set to the &$output parameter either. That being said, I'm not sure if the forward slashes would have worked on my system prior to the 22H2 update.
exec() only returns the last output line by default.
The wildcard probably works, but the output is just truncated.
Pass an variable by ref to exec() and log that:
<?php
$output = [];
exec('ls -lta /tmp/*', $output);
var_dump($output);
Without any additional changes, this returns the same as when I run ls -lta /tmp/* in my Bash terminal
That said, glob() is still the preferred way of getting data like this especcially since
You shouldn't parse the output of ls

Encoding php and python?

I wrote code that sends a query from php to a python script(some variable) and the python script does some things and returns some str. But this string is not valid! It has many question marks. I know that this problem appears when the encoding is not valid, but all files I'm using have the format utf-8.
My php file:
$search = $_POST["search"];
$search = shell_exec('get.py ' . $search);
print($search);
And as result I see this ������������. Python script code:
import sys
import pymorphy2
morph = pymorphy2.MorphAnalyzer()
word = sys.argv[1]
word = morph.parse(word)[0]
i = 0
result = ""
while i < len(word):
result = result + " " + word.make_agree_with_number(i).word
i = i + 1
print (result)
Some interesting things: all (2) files are in utf-8. In the python script I use coding utf-8 and it is not help. In php I use the iconv() function to change encoding, and use the mb_detect_encoding function to detect what the encoding is now. It shows utf-8. Please help me to make my encoding valid!
My version of python is 3.5, and I use .htaccess.
You should not be having this problem, and can narrow down what the problem is by using a minimal example:
In call_python.php:
<?php
$result = shell_exec('python called_python.py');
print("Python reports: ".$result);
In called_python.py:
#!/usr/bin/env python
print("I am a banana!")
We can see the result:
$ php call_python.php
Python reports: I am a banana!
I'm using a bash shell on a Mac system. If the above works for you, you know the problem is what you're doing inside the code. If not, you know that it has to do with the transport between the two scripts.

Executing python commands from php script

I have installed SymPi in the server and from the command line, I am able to execute the following.
python ./sympy-0.7.5/bin/isympy
(this will open a console where I can type mathematical expressions. then the following expression)
1 + 2
(will give 3 as output)
My aim is to do the same from php using shell_exec. I have written a php file as given below, but is not working.
$command = escapeshellcmd('python ./sympy-0.7.5/bin/isympy');
shell_exec($command);
$output = shell_exec('1 + 2');
Can anybody help me to figure out why this is not working?
Please note that the following script works fine which just execute a python script and retrieve the output.
$command = escapeshellcmd('python C:\PythonPrograms\test3.py');
$output = shell_exec($command);
echo $output;
My guess is that the working directory (cwd) of shell_exec is different from the one you're in when you execute it manually.
Your working example specifies a hard path that will work from anywhere. Whereas your not-working example specifies a relative path (./ is the cwd).
Convert your call to isympy to give its full path on disk. Or figure out how to set the cwd of shell_exec.
(If this doesn't solve it, say more than "is not working." What happens? An error? What is the full text of the error?)
Each time you run shell_exec, it opens a completely new instance of the shell.
Edit:
You can pass a command for python to execute like this:
$expression = '1 + 2';
$cmd = 'python -c \'print "%f" % (' . $expression . ')\'';
$output = shell_exec($cmd);
This, admittedly is not using sympy, but for simple mathmatical expressions you may not need to. If you do, you would just need to import the library in the same command, like this: python -c 'import sympy; print "%f" % sympy.sqrt(3)'
I could manage the desired result in a different way.
Created a python script which accepts the expression as the command line argument , execute and display the output.
Call this script from php by passing the expression as the command line argument.

Unicode to PHP exec

I have a Python file I'm calling with PHP's exec function. Python then outputs a string (apparently Unicode, based on using isinstance), which is echoed by PHP. The problem I'm running into is that if my string has any special characters in it (like the degree symbol), it won't output. I'm sure I need to do something to fiddle with the encoding, but I'm not really sure what to do, and why.
EDIT: To get an idea of how I am calling exec, please see the following code snippet:
$tables = shell_exec('/s/python-2.6.2/bin/python2.6 getWikitables.py '.$title);
Python properly outputs the string when I call getWikitables.py by itself.
EDIT: It definitely seems to be something either on the Python end, or in transmitting the results. When I run strlen on the returned values in PHP, I get 0. Can exec only accept a certain type of encoding?
Try setting the LANG environment variable immediately before executing the Python script per http://php.net/shell-exec#85095:
shell_exec(sprintf(
'LANG=en_US.utf-8; /s/python-2.6.2/bin/python2.6 getWikitables.py %s',
escapeshellarg($title)
));
(use of sprintf() to (hopefully) make it a little easier to follow the lengthy string)
You might also/instead need to do this before calling shell_exec(), per http://php.net/shell-exec#78279:
$locale = 'en_US.utf-8';
setlocale(LC_ALL, $locale);
putenv('LC_ALL='.$locale);
I have had a similar issue and solved it with the following. I don't understand why it is necessary, since I though all is already processed with UTF-8. Calling my Python script on the command line worked, but not with exec (shell_exec) via PHP and Apache.
According to a php forum entry this one is needed when you want to use escapeshellarg():
setlocale(LC_CTYPE, "en_US.UTF-8");
It needs to be called before escapeshellarg() is executed. Also, it was necessary to set a certain Python environment variable before the exec command (found an unrelated hint here):
putenv("PYTHONIOENCODING=utf-8");
My Python script evaluated the arguments like this:
sys.argv[1].decode("utf-8")
(Hint: That was required because I use a library to convert some arabic texts.)
So finally, I could imagine that the original question could be solved this way:
setlocale(LC_CTYPE, "en_US.UTF-8");
putenv("PYTHONIOENCODING=utf-8");
$tables = shell_exec('/s/python-2.6.2/bin/python2.6 getWikitables.py ' .
escapeshellarg($title));
But I cannot tell anything regarding the return value. In my case I could output it to the browser directly without any problems.
Spent many, many hours to find that out... One of the situations when I hate my job ;-)
This worked for me
setlocale(LC_CTYPE, "en_US.UTF-8");
putenv("PYTHONIOENCODING=utf-8");
$tables = shell_exec('/s/python-2.6.2/bin/python2.6 getWikitables.py ' .
escapeshellarg($title));
On php you can use methods like utf8_encode() or utf8_decode() to solve your problem.

PHP system returns 4

I want to convert a pdf file to an image with PHP, but i can't get the command worked. PHP returns a 4. I don't have any kind of idea what that can be.
I am using the next code:
$tmp = system("convert -version", $value);
var_dump($value);
Someone an idea?
try
exec("convert -version 2>&1", $out, $ret);
print_r($out);
it should tell you what's wrong
It looks like the -version flag is telling the convert software (looks like imagemagick) to respond with the major version number of that software. It looks like it is working correctly. You probably need to pass it the right flags to operate properly. I suggest reading the documentation to see what flags are required to convert PDFs.
try using some of the other system functions in PHP to get more detailed output.
exec("convert -version", $output, $value);
print_r($output);
The exec function above will give you all the output from the command in the $output parameter, as an array.
The return status (which will be held in the $value parameter in the exec call above or the system call in your original code) gives you the return value of the executed shell command.
In general, this will be zero for success, with non-zero integer return values indicating different kinds of error. So it appears there's something wrong with the command as you have it (possibly -version is not recognised: often you need a double hyphen before long-hand command-line options).
Incidentally, you may also find that the passthru function is more suited to your needs. If your convert program generates binary image data corresponding to the converted PDF, you can use passthru to send that image data directly to the browser (after setting the appropriate headers of course)
err... aren't you vardumping the wrong result? (I would var dump $tmp, not $value.)
I think the code should read:
$tmp = system("convert -version", $value);
var_dump($tmp);

Categories