Не пойму кое-что в функции mysql_escape_string. Часть 1.
От: Xavante  
Дата: 27.10.03 03:39
Оценка:
Greetings.

Занятную проблему нашел я себе на задницу. Такую:
Пишу интерфейс на VC++ 7.0 для базы данных, находящейся под MySQL 4.0.15a. С базой контактирую используя ODBC. В одну из таблиц надо грузить картинки (*.jpg, *.gif). Вскочил вопрос — cock? Шить к проге библиотеку libmySQL.dll ради одной единственной функции mysql_escape_string() не хочется. Да и пришьется ли она? Полез на www.mysql.com, скачал исходник Мускула и нашел в нем реализацию упомянутой функции. Служит она, как Вы наверное знаете, для экранирования в буфере опасных символов, перед отправкой его содержимого в BLOB-поле таблицы. Вот она:


ulong STDCALL mysql_escape_string(char* to, const char* from, ulong length)
{
    return mysql_sub_escape_string(default_charset_info, to, from, length);
}

static ulong mysql_sub_escape_string(CHARSET_INFO* charset_info, char* to,
    const char* from, ulong length)
{
    const char* to_start = to;
    const char* end;
#ifdef USE_MB
    my_bool use_mb_flag = use_mb(charset_info);    /* TRUE если в текущем наборе символов есть многобайтовые. */
#endif
    /* До тех пор, пока не будет достигнут байт, следующий за последним байтом буфера. */
    for (end = from + length; from != end; from++)
    {
#ifdef USE_MB
        int l;
        /* Если байт, на который указывает  from,  есть часть многобайтового символа,
            вернуть в переменную l общее число байт этого символа. */
if (use_mb_flag && (l = my_ismbchar(charset_info, from, end)))
 {
    while (l--)
    *to++ = *from++;    /* Сохранить в  to  все байты многобайтового символа. */
        from--;        /* Вернуть указатель на 1 байт назад.Т.е. на первый байт символа, следующего сразу за многобайтовым */
    continue;    /* Покинуть текущую итерацию цикла  for */
    }
#endif
        switch (*from)
        {
        case 0:
            /* Must be escaped for 'mysql' */
            *to++ = '\\';
            *to++ = '0';
            break;
        case '\n':
            /* Must be escaped for logs */
            *to++ = '\\';
            *to++ = 'n';
            break;
        case '\r':
            *to++ = '\\';
            *to++ = 'r';
            break;
        case '\\':
            *to++ = '\\';
            *to++ = '\\';
            break;
        case '\'':
            /* Апостроф */
            *to++ = '\\';
            *to++ = '\'';
            break;
        case '"': // Кавычка
            *to++ = '\\';
            *to++ = '"';
            break;
        case '\032':
            /* Ctrl-Z. This gives problems on Win32 */
            *to++ = '\\';
            *to++ = 'Z';
            break;
        default:
            *to++ = *from;     /* Любой неопасный символ */
        }
    }
    *to = 0;    /* Последним ставится разрыв строки */
    return (ulong) (to - to_start);    /* Длина  to  за вычетом разрыва строки */
}


Прежде всего, функция работает прекрасно. Но кое-что в ее реализации меня настораживает. А именно:

1. Зачем может понадобиться в каждой итерации цикла for узнавать значение флага use_mb_flag ?
if (use_mb_flag && (l = my_ismbchar(charset_info, from, end)))

Он устанавливается один раз в начале функции и значения больше не меняет.

2. Почему не прослешиваются многобайтовые символы? Что если частью многобайтового символа окажется \0 или \ или ' и т.п. ?

Это, собственно, еще не проблема. Проблема будет позже Сначала, мне хотелось бы услышать Ваше мнение по этим двум вопросам.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.