views:

6180

answers:

4

I'm looking for the alternative of mysql_real_escape_string() for MSSQL. Is addslashes() my best option or there is another alternative function that can be used?

Edit: Alternative for mysql_error() would also be useful.

+2  A: 

You could look into the PDO Library. You can use prepared statements with PDO, which will automatically escape any bad characters in your strings if you do the prepared statements correctly. This is for PHP 5 only I think.

addslashes() is not as good as mysql_real_escape_string() as the latter escapes a few extra bad characters if I recall correctly.

alex
With some of the halfassed behavior I've seen out of PDO, I'd have to do some serious testing before I trusted it to escape all data correctly.
chaos
@Chaos Really ? I'm unaware of this.. do you have a link to an article?
alex
What I was thinking of was the trouble this guy on here was having yesterday with PDO. Unrelated transaction stuff, but unimpressive. Combine that with all the history of inadequate data escaping in PHP (php.net telling people to use addslashes()!) and I get very suspicious.
chaos
Hmmm.. well hopefully they got the escaping portion correct.
alex
+5  A: 

addslashes() isn't fully adequate, but PHP's mssql package doesn't provide any decent alternative. The ugly but fully general solution is encoding the data as a hex bytestring, i.e.

$unpacked = unpack('H*hex', $data);
mssql_query('
    INSERT INTO sometable (somecolumn)
    VALUES (0x' . $unpacked['hex'] . ')
');

Abstracted, that would be:

function mssql_escape($data) {
    if(is_numeric($data))
        return $data;
    $unpacked = unpack('H*hex', $data);
    return '0x' . $unpacked['hex'];
}

mssql_query('
    INSERT INTO sometable (somecolumn)
    VALUES (' . mssql_escape($somevalue) . ')
');

mysql_error() equivalent is mssql_get_last_message().

chaos
Do you know the equivalent for mysql_insert_id() by any chance?
Click Upvote
Yeah, you do a SELECT @@IDENTITY.
chaos
Chaos, can you please give an example of an 'escape' function which would take a string as argument and return the hex alternative as a result using the method you gave? I'll accept your answer then
Click Upvote
At the moment I'm not sure about the double/quote requirement for hex values and how numeric values would be handled by this method. An example of using the function to escape a value and putting that in a query will be ideal. Thanks in advance
Click Upvote
Hopefully clearer now...
chaos
1 question, the value doesn't need to be enclosed by quotes? Also... have you done any testing on how this works with all character encoding types etc?
Click Upvote
Nope. It's a hex-string literal; if you enclosed it in quotes, you would be inserting the string '0xf00ba44' or whatever into your database instead of the original data. I haven't tested it with different encodings and I suggest anyone using this code do so before doing anything important with it.
chaos
You should use SELECT IDENTITY_SCOPE(); from within your same connection to retrieve your ID field instead of @@IDENTITY - it is more reliable.
Redbeard 0x0A
Oops, its SELECT SCOPE_IDENTITY()!
Redbeard 0x0A
Function is not right for what he was asking.
genio
@genio: Mmm, great, except it actually is. I don't suppose you'd explain what you consider to be the problem?
chaos
A: 

You could roll your own version of mysql_real_escape_string, (and improve upon it) with the following regular expression: [\000\010\011\012\015\032\042\047\134\140]. That takes care of the following characters: null, backspace, horizontal tab, new line, carriage return, substitute, double quote, single quote, backslash, grave accent. Backspace and horizontal tab are not supported by mysql_real_escape_string.

Scott
+6  A: 
function ms_escape_string($data) {
        if ( !isset($data) or empty($data) ) return '';
        if ( is_numeric($data) ) return $data;

        $non_displayables = array(
            '/%0[0-8bcef]/',            // url encoded 00-08, 11, 12, 14, 15
            '/%1[0-9a-f]/',             // url encoded 16-31
            '/[\x00-\x08]/',            // 00-08
            '/\x0b/',                   // 11
            '/\x0c/',                   // 12
            '/[\x0e-\x1f]/'             // 14-31
        );
        foreach ( $non_displayables as $regex )
            $data = preg_replace( $regex, '', $data );
        $data = str_replace("'", "''", $data );
        return $data;
    }

Some of the code here was ripped off from CodeIgniter. Works well and is a clean solution.

genio
Confirmed to work!! Thanks man!
KyleFarris
Why do you need the `preg_replace`? Isn't the `str_replace` sufficient?
Gabe
gabe: The preg_replace in this case was to allow me to use the ranges afforded to me in regular expressions character classes. There would be a lot more string replaces in this one otherwise.
genio
-1. It is not the responsibility of a quoting function to mangle data -- all it should do is make sure the string is in such a format that it can be added to an SQL statement and survive unmodified.
cHao