While I definitely agree with the comments and answer that using prepared statements, and not doing this yourself is both smarter, better in many ways and always recommended when you can use them. While you may not have a security problem now, one may suddenly appear in the future; and the risk with prepared statements is just much, much lower. If you can find a workaround for it, do it!
I feel like I have to give that disclaimer, in order to be taken seriously here.
Because, I also believe it's definitely possible to do all the escaping manually; given that the environment is controlled. This is no different than escaping for other formats, such as javascript. Sometimes this is needed. I, for one, once had a need to create a SQL export script with no database available.
To do this correctly, the following must be assumed:
- The input string is UTF-8. You validated this.
- When you execute the mysql string later down the road, the full sql statement is in UTF-8, and so is the connection.
- No crazy stuff is going on with php's mbstring function overloading.
- You don't trust my untested code, and verify what I'm saying ;)
Why is UTF-8 so important? Read this article
Given those two points, to emulate mysql_real_escape_string, you must escape the following characters:
NUL (ASCII 0),
, , \, ', ", and Control-Z.
Source: php.net
To do this, this should be sufficient:
$translate = array(
"\x00" => '\\0',
"
" => '\
',
"" => '\',
"'" => '\\\'',
"\"" => '\\"',
"\x1a" => '\\Z',
);
$output = "'" . strtr($input, $translate) . "'";
As you can see, I did still make sure that my output was surrounded by quotes. Without that, this escaping technique (nor mysqli::real_escape_string
) would not be sufficient.
Alternative techniques I've seen:
- Splitting up every byte, and surrounding it with MySQL's CHAR function.
- Base64-encoding the string in PHP, and base64-decoding it with MySQL 5.6's FROM_BASE64 function.