addslashes与mysql_real_escape_st…

来源:互联网 发布:提取微信网页数据库 编辑:程序博客网 时间:2024/05/01 13:12
addslashes和mysql_real_escape_string.都是为了使数据安全的插入到数据库中而进行过滤.那么这两个函数到底是有什么区别呢??
我们今天来简单的看下..
首先.我们还是从PHP手册入手..
手册上addslashes转义的字符是单引号(')、双引号(")、反斜线(\)与NUL(NULL 字符)。
mysql_real_escape_string转义的字符并没有被提到.只是说了一句
注意: mysql_real_escape_string() 并不转义% 和_。
为什么PHP手册没有说呢?因为其实这是个MySql的C的API.所以我们需要查下MySql手册..上面是这么说的.
编码的字符为NUL (ASCII0)、'\n'、'\r'、'\'、'''、'"'、以及Control-Z(请参见9.1节,“文字值”)。(严格地讲,MySQL仅需要反斜杠和引号字符,用于引用转义查询中的字符串。该函数能引用其他字符,从而使得它们在日志文件中具有更好的可读性)。
 
不得不说一句.MySql手册上面的话总是令人费解的..
 
我们为了更深层次的探究这两个函数的不同..还是去看一看PHP的源码吧..
 
这是PHP的addslashes函数..
 
   PHP_FUNCTION(addslashes)
    {
        zval **str;
       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1,&str) == FAILURE) {
            WRONG_PARAM_COUNT;
        }
        convert_to_string_ex(str);
       if (Z_STRLEN_PP(str) == 0) {
            RETURN_EMPTY_STRING();
        }
        RETURN_STRING(php_addslashes(Z_STRVAL_PP(str),
                                     Z_STRLEN_PP(str),
                                     &Z_STRLEN_P(return_value), 0
                                     TSRMLS_CC), 0);
    }
 
很显然.它调用了php_addslashes.我们继续看这个函数
 
    PHPAPI char*php_addslashes(char *str, int length, int *new_length, intshould_free TSRMLS_DC)
    {
       return php_addslashes_ex(str, length, new_length, should_free, 0TSRMLS_CC);
    }
 
结果又是是在调用php_addslashes_ex 我们就像在剥洋葱一样..一步一步的接近真理..
 
    PHPAPI char*php_addslashes_ex(char *str, int length, int *new_length, intshould_free, int ignore_sybase TSRMLS_DC)
    {
       
       char *new_str;
       char *source, *target;
       char *end;
       int local_new_length;
               
       if (!new_length) {
            new_length = &local_new_length;
        }
       if (!str) {
            *new_length = 0;
           return str;
        }
        new_str = (char *) safe_emalloc(2, (length ? length : (length =strlen(str))), 1);
        source = str;
        end = source + length;
        target = new_str;
       
       if (!ignore_sybase &&PG(magic_quotes_sybase)) {
           while (source < end) {
               switch (*source) {
                   case '\0':
                        *target++ = '\\';
                        *target++ = '0';
                       break;
                   case '\'':
                        *target++= '\'';
                        *target++ = '\'';
                       break;
                   default:
                        *target++ = *source;
                       break;
                }
                source++;
            }
        } else {
           while (source < end) {
               switch (*source) {
                   case '\0':
                        *target++ = '\\';
                        *target++ = '0';
                       break;
                   case '\'':
                   case '\"':
                   case '\\':
                        *target++ = '\\';
                       
                   default:
                        *target++ = *source;
                       break; 
                }
           
                source++;
            }
        }
       
        *target = 0;
        *new_length = target - new_str;
       if (should_free) {
            STR_FREE(str);
        }
        new_str = (char *) erealloc(new_str, *new_length + 1);
       return new_str;
    }
 
上面的函数已经非常清楚的描述出都要转义哪些字符了..现在我们去看一看mysql_real_escape_string
 
这个不在string.c里了..是在mysql扩展中.
 
   PHP_FUNCTION(mysql_real_escape_string)
    {
        zval *mysql_link = NULL;
       char *str;
       char *new_str;
       int id = -1, str_len, new_str_len;
        php_mysql_conn *mysql;
       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r",&str, &str_len,&mysql_link) == FAILURE) {
           return;
        }
       if (ZEND_NUM_ARGS() == 1) {
            id =php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
            CHECK_LINK(id);
        }
        ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *,&mysql_link, id, "MySQL-Link", le_link,le_plink);
        new_str = safe_emalloc(str_len, 2, 1);
        new_str_len =mysql_real_escape_string(&mysql->conn,new_str, str, str_len);
        new_str = erealloc(new_str, new_str_len + 1);
        RETURN_STRINGL(new_str, new_str_len, 0);
    }
 
这个函数并没有像上面的那样剥洋葱..
 
而是直接调用了MySql的C的API.mysql_real_escape_string()..
 
需要注意的是.这个函数在调用mysql_real_escape_string这个API之前.先是判断了是否连接上了数据库
 
CHECK_LINK(id);   //就是这句
 
所以这就意味着mysql_real_escape_string必须是连接数据库之后才能使用.为了证实这一点.
我们来简单的实验下.
 
   <?php
    echomysql_real_escape_string("fdsafda'fdsa");
 
结果
Warning: mysql_real_escape_string()[function.mysql-real-escape-string]: Access denied for user'ODBC'@'localhost' (using password: NO) in PHPDocument1on line 2
 
Warning: mysql_real_escape_string()[function.mysql-real-escape-string]: A link to the server could notbe established in PHPDocument1 on line 2
 
果然报错了..显示没有链接上数据库..
 
好了..总结就先告一段落..
 
我们终于明白为什么那么多开源的程序比如Discuz用addslashes而不用mysql_real_escape_string了.
 
所以呢.以后也就用addslashes好了..暂时可以忘记掉mysql_real_escape_string了
0 0
原创粉丝点击