Find position of console escape code in string - php

tl;dr How do I write strpos($haystack, '^[[H^[[2J') in PHP?
A linux command line app delivers a screen-full of data followed by a console escape code to return the cursor to the "home" position in a regular loop. To access the data I piped the output to my own script like so:
$ ./otherapp | php myscript.php
It's a continuous stream of data so I use this example for non-blocking stream consumption.
Now to decode the output I need to grab a full frame/screen full of data. The escape codes are shown in nano as ^[[H and ^[[2J. The easiest way seems to be detecting these escape codes and using the output between them.
How are the escape codes represented in a PHP string? Can I use strpos (or mbstring equivalent) to detect their position?

It seems you're on a Unix environment. To achieve what your escape codes do, you can try with echo -en "\033[H" and echo -en "\033[2J", so I guess you should try something like strpos('\033[H\033[2J', $haystack).
Maybe you'll need to add an extra backslash ('\\\033[H\\\033{2J').
Since \033 means "the byte with octal value 33", which is ESC, this should work:
strpos("\e[H\e[2J", $haystack)
You need to enclose it in double-quotes (") if you want PHP to interpret escape sequences for special characters.

Related

why is curl waiting for a keypress?

I simply want to run the following command:
curl https://jkanime.net/um.php?e=VTJpeCsrL3BVY2xMaEd0YWhyM1k4SDdHelZ4OGZSeXFsOHBla1QrcnBPQm4wUWc1eE1TOThmWlBOb2xLOEJCeWlGenpML2tYelA3Tm8xU1lDMDRwUlE9PTo616MlXtdmRfi6FOwaoBRqeA--&t=5ec9cff996b02bf751b55c92c4cb1170
It seems to connect just fine, but it hangs waiting for a keypress. How can I automatize this in a script?
EDIT:
I have absolutely no idea but it solved by erasing the -- part of the URL. Can someone explain to me why?
In bash, you must use quotes (single or double, that depends what you want to do) to build one complete string by escaping some characters : ` $ ( ) [ ] { } & | space
So, use quotes around the URL:
curl --url 'https://jkanime.net/um.php?e=VTJpeCsrL3BVY2xMaEd0YWhyM1k4SDdHelZ4OGZSeXFsOHBla1QrcnBPQm4wUWc1eE1TOThmWlBOb2xLOEJCeWlGenpML2tYelA3Tm8xU1lDMDRwUlE9PTo616MlXtdmRfi6FOwaoBRqeA--&t=5ec9cff996b02bf751b55c92c4cb1170'
You don't describe your environment, but it's probably your shell interpreting the unquoted hyphens. In bash, double hyphens terminate processing. If you surround your URL with quotes, it will avoid this behavior and pass the quoted string to curl.

PHP - escape backslash doesn't work

Well the title sums it up. If I do this:
fwrite($handle, 'test\r\ntest');
I get litreally that written to a file. That is:
test\r\ntest
It doesn't work for echo or any other function manipulates strings.
This became a problem when I needed to write to a printer in the serial port using ESC/POS. If I use PHP, it prints a bunch of question makrs and french characteres. With Python (plus pyserial), using the following code, works amazingly:
from __future__ import print_function
import serial
ser = serial.Serial('COM4');
ser.write('\x1b\x40');
ser.write('\x0a');
ser.write('\x0a');
ser.write('Hello there');
ser.write('\x0a');
ser.write('\x1d\x56\x42\x03');
My system:
WAMP 2.4 (PHP 5.4.16, Apache 2.4.4) on Windows 7 Home Basic x64
For the backslash sign to escape special characters you need to use double-quoted strings, not single-quoted ones, try these :
fwrite($handle, 'test\r\ntest'); // not working
fwrite($handle, "test\r\ntest"); // works as expected
It may be worth noting that the problem could have been skipped altogether if your data came from another source (non-php file, web form), and happens only when you hardcode your strings inside your script file. For further details, feel free to browse the relevant manual page :
http://www.php.net/manual/en/language.types.string.php
Using a single quote will literally write your string.
To use escaped characters you need to use a double quote instead :
echo "This output will \n expand";
http://www.php.net/manual/en/language.types.string.php
Try using " instead of ' for these escape sequences:
fwrite($handle, "test\r\ntest");

PHP hash function doing something strange with "\v" - how do I enable escaping from the command line?

If I run the following in PHP
<?=hash('sha256', "\v");?>
I get this hash:
e7cf46a078fed4fafd0b5e3aff144802b853f8ae459a4f0c14add3314b7cc3a6
However if I put \v into any of the online tools like http://www.xorbin.com/tools/sha256-hash-calculator, I get the following hash:
1b5cec8c46451b5375ea7e61f310fe831ad17f62098beb7a5bfce304821e3f78
I realise that PHP is obviously hashing the escaped value, rather than the actual string,
\v vertical tab (VT or 0x0B (11) in ASCII) (since PHP 5.2.5)
(Reference: http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.double)
but what I'm trying to figure out is how to get the same result as the PHP function using the command line or one of the online tools - I've tried VT, vt, 0x0B and 11 - but none of them give me the same result.
Thanks for your help!
UPDATE: As #Alex-Info.net pointed out, changing the double quotes to single quotes will treat the \v as a string, but unfortunately I can't change the PHP in this instance.
As I said, I'd favor chaing your PHP code to match the online/commandline apps. Single quotes will not escape, and gets the results you mentionned.
<?= hash('sha256', '\v'); ?>
EDIT: Since you can't change the PHP code, here's how to tweak the command line so that it escapes correctly like PHP does:
echo -e -n "\v" | openssl dgst -sha256 , -e enables escaping.

PHP exec() with double quote argument

I've been having trouble running a command using PHP's exec() function on Windows. Per a comment on PHP's site on exec():
In Windows, exec() issues an internal call to "cmd /c your_command".
My command looks like:
"path\to\program.exe" -flag1 attribute1 -flag2 attribute2 -flag3 "attribute3 attribute4"
Under regular execution of this command in my local command prompt, without the /c flag, the command runs fine. However, with the introduction of the /c flag, command prompt tells me that "The system cannot find the path specified."
I think the command prompt is interpreting the double-quoted argument as a path to another file, but that's the furthest I've gotten with this problem.
Does anybody have any ideas on how to get past this? Thanks!
I also encountered this issue, and the cause of it is, indeed, the internal use of "cmd /c" as described in your own answer.
I have done some investigation, and have found that this was resolved in PHP 5.3, which is why some commenters were unable to reproduce it.
It was fixed in the following commit:
https://github.com/php/php-src/commit/19322fc782af429938da8d3b421c0807cf1b848a#diff-15f2d3ef68f383a87cce668765721041R221
For anyone who still needs to support PHP 5.2, it is fairly easy to replicate the fix in your own code. Instead of:
$cmd = "...any shell command, maybe with multiple quotes...";
exec($cmd);
use
function safe_exec($cmd, &$output = null, &$result_code = null) {
if (strtoupper(substr(php_uname('s'), 0, 3)) == "WIN"
&& version_compare(PHP_VERSION, "5.3", "<"))
{
$cmd = '"' . $cmd . '"';
}
return exec($cmd, $output, $result_code);
}
$cmd = "...any shell command, maybe with multiple quotes...";
safe_exec($cmd);
This replicates the behaviour of PHP 5.3 and above, in the same way as in the above-linked commit.
Note that this applies to all shell commands, not just exec() as used in my example.
I've figured out the answer by myself...
After perusing cmd.exe's /? and trying to decipher that, I've noticed one important section:
If all of the following conditions are met, then quote characters on the command line are preserved:
No /S switch (Strip quotes)
Exactly two quote characters
No special characters between the two quote characters, where special is one of: & < >( ) # ^ |
There are one or more whitespace characters between the the two quote characters
The string between the two quote characters is the name of an executable file.
Otherwise, old behavior is to see if the first character is a quote character and if so, strip the leading character and remove the last quote character on the command line, preserving any text after the last quote character. To negate this behaviour use a double set of quotes "" at the start and end of the command line.
It seems as though if there more than one pair of quotes at any time, quotation marks will be stripped from the second pair of quotes and on.
A relevant question: How do I deal with quote characters when using cmd.exe but not completely relevant, since PHP will not allow you to modify its exec() command by putting an /S flag on its call (which would definitely be a lot easier).
I've managed to work around this problem by directly changing directories with chdir() to the folder where the .exe is located, then chdir()'ing back to my original working directory. It's an extremely hacky solution, given the case that I'm lucky that I only have one set of arguments using double quotes. If anybody were to have multiple arguments using double quotes, I wouldn't know how to solve that...
Just a guess (I am not familiar with PHP on windows): maybe escape the quotes as " becoming ""?
"path\to\program.exe" -flag1 attribute1 -flag2 attribute2 -flag3 ""attribute3 attribute4""
Whatever the solution is, make sure that when there's some form of user-input that gets passed to this command as arguments that you use escapeshellarg and/or escapeshellcmd.
I hope it will help
escapeshellarg() — Escape a string to be used as a shell argument
escapeshellcmd() — Escape shell metacharacters

PHP exec() and spaces in paths

I'm executing the following in a PHP application:
$source = '/home/user/file.ext';
$output_dir = $this->setOutputString();
chdir('/home/ben/xc/phplib/bgwatcher-2011a/a01/');
exec('php bin/createjob.php $source $output_dir', $output);
return $output[0];
The problem is this: I have control over $source, but not $output_dir, which is a legacy Windows filesystem, and there are spaces in the path. An example $output_dir is:
/home/vol1/district id/store id/this_is_the_file.html
When inserting the output string into the exec() function, I have tried both:
addslashes($output_dir) and '"' . $output_dir . '"' to escape the entire output string. In the first case, the path gets concatenated to:
/home/vol1/districtthis_is_the_file.html
... where everything between the first space and the filename gets dropped. In the second case, exec() appears to throw a shoe and doesn't execute properly - unfortunately, the error message is getting lost in the machinery - I can provide it if it's absolutely necessary, but I'm also under time constraints to find a solution.
What's the solution, here? Do I sprintf() the entire string for exec()? I'm very confused as to why addslashes isn't working correctly to escape the spaces, and I assume it has something to do with sanitization with exec(), but I can't find any documentation to back it up.
Update: I've tried escapeshellarg() and preg_replace() without success. Thinking about this further, do I need to double-escape the path? Or escape the path and the command? If the path is being unescaped once by exec(), and once by PHP before it executes the command, does it stand to reason that I need to account for both escapes? Or is that not how it works?
I don't believe addslashes() does anything with spaces. escapeshellarg() might be what you want instead. Docs on escapeshellarg
From the PHP doc (here),
Returns a string with backslashes before characters that need to be quoted in database queries etc. These characters are single quote ('), double quote ("), backslash () and NUL (the NULL byte).
This won't do anything to the spaces. What you will need to do is use str_replace() to add slashes, like this:
$new_string = str_replace(" ", "\\ ", $old_string);
According to the PHP docs,
Returns a string with backslashes before characters that need to be quoted in database queries etc. These characters are single quote ('), double quote ("), backslash () and NUL (the NULL byte).
Looks like you'll have to preg_replace the spaces yourself.
Edit:
Even though this is the topic of another discussion, if performance is an issue, then after looking into it a little more, it seems that str_replace is actually quite a bit faster than preg_replace:
The test labeled "str_replace()" was
the faster by 0.9053 seconds (it took
10.3% the time.)
The first test took 1.0093 seconds. (preg_replace)
The second test took 0.104 seconds. (str_replace)
Benchmark found here.
I've used exec() with paths with spaces before, on both Windows and Linux hosts, and in both cases quoting the path worked perfectly for me.
That said, if you have no control over the safety of a shell argument, always run it through escapeshellarg() first!
You can very well use shell quotes, since that is what all exec commands run through:
exec("php bin/createjob.php '$source' '$output_dir'", $output);
It btw works not just for arguments, but also for the command itself:
exec('"/bin/echo" "one parameter"');
Use escapeshellcmd() anyway.
this works for me when using exec() with soffice(LibreOffice):
$file_name = "Some, file name.xlsx";
exec('/usr/bin/soffice --headless --convert-to pdf '."'".$file_name."'".' 2>&1', $output, $r);
You can use double quotes and escape character together to work out this.
$fileName = "filename with spaces.pdf";
exec("php bin/createjob.php >\"".$fileName."\" 2> error.log" , $output, $return);

Categories