这篇 文章已经是07年的了,不过,我一直没有关注过drupal的db类,所以对于这方面我也根本 就没有在意过。8过,我在我的siterpc中,我也是采用了sprintf的写法,不是为了安全,而是为了格式化。因为在siterpc里我们几乎不接受外部变量,所有的变量都是由我们自己传入,所以对于安全方便忽略了很多。但还是用sprintf来格式化SQL语句了。

因此看到这篇drupal的db_query安全过滤,突然发现,可以让我的代码少写很多了。(参数可变时请使用vsprintf)

以下是原文 :

Drupal通过C风格的字符串输出格式实现了对sql语句的安全过滤。
使用方法:

db_query("SELECT n.nid FROM {node} n WHERE n.type = '%s'", $type);//正确做法
//这不等于以下语句,使用sprintf并不能避免mysql注入。
db_query(sprintf("SELECT n.nid FROM {node} n WHERE n.type = '%s'", $type)); //不正确
drupal db_query核心代码如下:
/**
* Indicates the place holders that should be replaced in _db_query_callback().
*/
define('DB_QUERY_REGEXP', '/(%d|%s|%%|%f|%b)/');

/**
* Runs a basic query in the active database.
*
* User-supplied arguments to the query should be passed in as separate
* parameters so that they can be properly escaped to avoid SQL injection
* attacks.
*
* @param $query
* A string containing an SQL query.
* @param ...
* A variable number of arguments which are substituted into the query
* using printf() syntax. Instead of a variable number of query arguments,
* you may also pass a single array containing the query arguments.

* Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
* in '') and %%.
*
* NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
* and TRUE values to decimal 1.
*
* @return
* A database query result resource, or FALSE if the query was not
* executed correctly.
*/
function db_query($query) {
$args = func_get_args();
array_shift($args);
$query = db_prefix_tables($query);
if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
$args = $args[0];
}
_db_query_callback($args, TRUE);
$query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
return _db_query($query);
}

/**
* Helper function for db_query().
*/
function _db_query_callback($match, $init = FALSE) {
static $args = NULL;
if ($init) {
$args = $match;
return;
}

switch ($match[1]) {
case '%d': // We must use type casting to int to convert FALSE/NULL/(TRUE?)
return (int) array_shift($args); // We don't need db_escape_string as numbers are db-safe
case '%s':
return db_escape_string(array_shift($args));
case '%%':
return '%';
case '%f':
return (float) array_shift($args);
case '%b': // binary data
return db_encode_blob(array_shift($args));
}
}
简单的对一些输入做了处理。参考: http://drupal.org/node/101496

原文来自于:http://www.luochunhui.com/id/315