PHP - escape backslash doesn't work - php

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");

Related

Find position of console escape code in string

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.

PHP Line Feeds "\n" Not Saving

For some reason with my code which I'm using \n to break the line, isn't working.
It is outputting without breaking the lines.
$file = "availables.txt";
$current .= $test."\n";
file_put_contents($file, $current);
I'm not sure what's wrong but I read that using single quotes (') doesn't work and I have to use double quotes (") which is what I'm using.
I couldn't really find much but I'm sure this is just a simple issue :)
As alluded to in the comments the issue is in selecting the correct line ending symbol for the platform.
The core constant PHP_EOL will do this for you allowing you to create portable code.
The correct 'End Of Line' symbol for this platform. Available since PHP 4.3.10 and PHP 5.0.2
It's true that a line feed character enclosed in single quotes won't work, that's simply because PHP will insert a backspace \ followed by an n into the file. This results in the ASCII/UTF-8 hex code 0x2F0x6E instead of simply 0xA.
Using either "\n" or the predefined constant PHP_EOL which will always contain the correct line feed combination for your platform will resolve this issue.
There's absolutely nothing wrong with the code you posted in your question. So what's wrong? My guess is the program you use to view the resulting file. Some broken Windows applications won't read the line feed correctly because they expect the file to use Windows line feeds (which is a combination of line feed and carriage return as you might know).
You're using PHP, output the file in your browser (no matter which), they'll handle it correctly. Simply:
<?php
header("content-type: text/plain");
echo "hello\nworld";
And you'll see that everything is fine.
You can write you variable inside double quotes like this
$current .= "$test\n";

PHP SSH Lib, echoing to a file

I'm trying to create a PHP script that creates a file on a remote linux server through ssh, and echos the file contents into it.
However, I cannot figure out how to correctly and safely encode/escape the file contents, so that the contents don't get interpreted as commands.
I'm using phpseclib from here.
I've tried something like
echo $ssh->exec('sudo echo "' . escapeshellarg($newConfig) . '" > /etc/nginx/nginx.conf') . "\n";
but without success.
Thanks,
Steve
What about escapeshellcmd? Quoting the description of that vs escapeshellarg:
escapeshellarg() adds single quotes around a string and quotes/escapes
any existing single quotes allowing you to pass a string directly to a
shell function and having it be treated as a single safe argument.
...and...
escapeshellcmd() escapes any characters in a string that might be used
to trick a shell command into executing arbitrary commands. This
function should be used to make sure that any data coming from user
input is escaped before this data is passed to the exec() or system()
functions, or to the backtick operator.
Following characters are preceded by a backslash: #&;`|*?~<>^()[]{}$\,
\x0A and \xFF. ' and " are escaped only if they are not paired. In
Windows, all these characters plus % are replaced by a space instead.
I was going about this all wrong, I should have used Net_SFTP instead of NET_SSH for this sort of thing.

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);

PHP 'addslashes' not behaving as expected

This has been driving be crazy, but I can't seem to find an answer. We run a technical knowledge base that will sometimes include Windows samba paths for mapping to network drives.
For example: \\servername\sharename
When we include paths that have two backslashes followed by each other, they are not escaped properly when running 'addslashes'. My expected results would be "\\\\servername\\sharename", however it returns "\\servername\\sharename". Obviously, when running 'stripslashes' later on, the double backslash prefix is only a single slash. I've also tried using a str_replace("\\", "\", $variable); however it returns "\servername\sharename" when I would expect "\\servername\sharename".
So with addslashes, it ignores the first set of double-backslashes and with str_replace it changes the double-backslashes into a single, encoded backslash.
We need to run addslashes and stripslashes for database insertion; using pg_escape_string won't work in our specific case.
This is running on PHP 5.3.1 on Apache.
EDIT: Example Code
$variable = 'In the box labeled Folder type: \\servername\sharename';
echo addslashes($variable);
This returns: In the box labeled Folder type: \\servername\\sharename
EDIT: Example Code #2
$variable = 'In the box labeled Folder type: \\servername\sharename';
echo str_replace('\\', '\', $variable);
This returns: In the box labeled Folder type: \servername\sharename
I'd also like to state that using a single quotes or double-quotes does not give me different results (as you would expect). Using either or both give me the same exact results.
Does anyone have any suggestions on what I can possibly do?
I think I know where is a problem. Just try to run this one:
echo addslashes('\\servername\sharename');
And this one
echo addslashes('\\\\servername\sharename');
PHP escapes double slashes even with single quotes, because it is used to escape single quote.
Ran a test on the problem you described, and the only way I could get the behavior you desired was to couple a conditional with a regex and anticipate the double slashes at the start.
$str = '\\servername\sharename';
if(substr($str,0,1) == '\\'){
//String starts with double backslashes, let's append an escape one.
//Exclaimation used for demonstration purposes.
$str = '\\'.$str;
echo addslashes(preg_replace('#\\\\\\\\#', '!',$str ));
}
This outputs:
!servername\\sharename
While this may not be an outright answer, it does work and illustrates a difference in how the escape character is treated by these two constructs. If used, the ! could easily be replaced with the desired characters using another regex.
This is not a problem with addslashes, it is a problem with the way you are assigning the string to your variable.
$variable = 'In the box labeled Folder type: \\servername\sharename';
echo $variable;
This returns: In the box labeled Folder type: \servername\sharename
This is because the double backslash is interpreted as an escaped backslash. Use this assignment instead.
$variable = 'In the box labeled Folder type: \\\\servername\\sharename';
I've determined, with more testing, that it indeed is with how PHP is handling hard-coded strings. Since hard-coded strings are not what I'm interested in (I was just using them for testing/this example), I created a form with a single text box and a submit button. addslashes would correctly escape the POST'ed data this way.
Doing even more research, I determined that the issue I was experiencing was with how PostgreSQL accepts escaped data. Upon inserting data into a PostgreSQL database, it will remove any escape characters it is given when it actually places the data in the table. Therefore, stripslashes is not required to remove escape characters when pulling the data back out.
This problem stemmed from code migration from PHP 4.1 (with Magic Quotes on) to PHP 5.3 (with Magic Quotes deprecated). In the existing system (PHP4), I don't think we were aware that Magic Quotes were on. Therefore, all POST data was being escaped already and then we were escaping that data again with addslashes before inserting. When it got inserted into PostgreSQL, it would strip one set of slashes and leave the other, therefore requiring us to stripslashes on the way out. Now, with Magic Quotes off, we escape with addslashes but are not required to use stripslashes on the way out.
It was very hard to organize and determine exactly where the problem lay, so I know this answer is a little off to my original question. I do, however, thank everyone who contributed. Having other people sound off on their ideas always helps to make you think on avenues you may not have on your own.

Categories