mysqli_real_escape_string:
http://jp2.php.net/manual/ja/mysqli.real-escape-string.php
上記マニュアルによると、
- NUL (ASCII 0), \n, \r, \, ', ", および Control-Zの文字をエスケープ
- 接続先MySQLの文字セットの考慮(?) ※具体的に思いつかない
の2つの処理で済みそうですが、それ以外に必要な処理があれば教えてください。
ちなみに自前で実装する場合、MySQLの文字セットとエスケープ対象の文字列はどちらもutf8mb4で固定になります。
具体的なソースがあると分かりやすくて有り難いです。
宜しくお願いします。
本物を見るのが一番早いと思います。
PHP の Mysqli は、Mysql の関数を呼び出しているだけです。
MySQL-5.6.14 から実装を抜き出しました。
mysql_real_escape_string() の実装は libmysql/libmysql.c にあります。
/* Add escape characters to a string (blob?) to make it suitable for a insert to should at least have place for length*2+1 chars Returns the length of the to string */ ulong STDCALL mysql_escape_string(char *to,const char *from,ulong length) { return (uint) escape_string_for_mysql(default_charset_info, to, 0, from, length); } ulong STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, ulong length) { if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) return (uint) escape_quotes_for_mysql(mysql->charset, to, 0, from, length); return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length); }
実装は、この二つの関数になっています。
後者は、クォーテーションのエスケープだけを行います。
escape_string_for_mysql() の実装は mysys/charset.c にあります。
size_t escape_string_for_mysql(const CHARSET_INFO *charset_info, char *to, size_t to_length, const char *from, size_t length) { const char *to_start= to; const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); my_bool overflow= FALSE; #ifdef USE_MB my_bool use_mb_flag= use_mb(charset_info); #endif for (end= from + length; from < end; from++) { char escape= 0; #ifdef USE_MB int tmp_length; if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) { if (to + tmp_length > to_end) { overflow= TRUE; break; } while (tmp_length--) *to++= *from++; from--; continue; } /* If the next character appears to begin a multi-byte character, we escape that first byte of that apparent multi-byte character. (The character just looks like a multi-byte character -- if it were actually a multi-byte character, it would have been passed through in the test above.) Without this check, we can create a problem by converting an invalid multi-byte character into a valid one. For example, 0xbf27 is not a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \) */ if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1) escape= *from; else #endif switch (*from) { case 0: /* Must be escaped for 'mysql' */ escape= '0'; break; case '\n': /* Must be escaped for logs */ escape= 'n'; break; case '\r': escape= 'r'; break; case '\\': escape= '\\'; break; case '\'': escape= '\''; break; case '"': /* Better safe than sorry */ escape= '"'; break; case '\032': /* This gives problems on Win32 */ escape= 'Z'; break; } if (escape) { if (to + 2 > to_end) { overflow= TRUE; break; } *to++= '\\'; *to++= escape; } else { if (to + 1 > to_end) { overflow= TRUE; break; } *to++= *from; } } *to= 0; return overflow ? (size_t) -1 : (size_t) (to - to_start); }
ざっと見た感じ、マニュアルに書いた以上のことはやってません(当たり前か)。
escape_quotes_for_mysql() の実装も mysys/charset.c にあります。
省略しますが、escape_string_for_mysql() から、シングルクォートのエスケープだけを抜き出したような実装になってます。