%? no longer handles arrays and hashes for security purposes
those are moved into %l?, %ll?, %hc, %ha, %ho for different uses
This commit is contained in:
@@ -106,7 +106,7 @@ It's dead simple. I don't even want to think about how many lines
|
|||||||
you'd need to pull this off in PDO.
|
you'd need to pull this off in PDO.
|
||||||
|
|
||||||
// Insert 2 rows at once
|
// Insert 2 rows at once
|
||||||
DB::query("INSERT INTO %b %lb VALUES %?", 'accounts',
|
DB::query("INSERT INTO %b %lb VALUES %ll?", 'accounts',
|
||||||
array('username', 'password', 'last_login_timestamp'),
|
array('username', 'password', 'last_login_timestamp'),
|
||||||
array(
|
array(
|
||||||
array('Joe', 'joes_password', new DateTime('yesterday')),
|
array('Joe', 'joes_password', new DateTime('yesterday')),
|
||||||
|
|||||||
96
db.class.php
96
db.class.php
@@ -306,7 +306,7 @@ class MeekroDB {
|
|||||||
$params = array_shift($args);
|
$params = array_shift($args);
|
||||||
$where = array_shift($args);
|
$where = array_shift($args);
|
||||||
|
|
||||||
$query = str_replace('%', $this->param_char, "UPDATE %b SET %? WHERE ") . $where;
|
$query = str_replace('%', $this->param_char, "UPDATE %b SET %hc WHERE ") . $where;
|
||||||
|
|
||||||
array_unshift($args, $params);
|
array_unshift($args, $params);
|
||||||
array_unshift($args, $table);
|
array_unshift($args, $table);
|
||||||
@@ -319,6 +319,7 @@ class MeekroDB {
|
|||||||
$keys = $values = array();
|
$keys = $values = array();
|
||||||
|
|
||||||
if (isset($datas[0]) && is_array($datas[0])) {
|
if (isset($datas[0]) && is_array($datas[0])) {
|
||||||
|
$var = '%ll?';
|
||||||
foreach ($datas as $datum) {
|
foreach ($datas as $datum) {
|
||||||
ksort($datum);
|
ksort($datum);
|
||||||
if (! $keys) $keys = array_keys($datum);
|
if (! $keys) $keys = array_keys($datum);
|
||||||
@@ -326,6 +327,7 @@ class MeekroDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
$var = '%l?';
|
||||||
$keys = array_keys($datas);
|
$keys = array_keys($datas);
|
||||||
$values = array_values($datas);
|
$values = array_values($datas);
|
||||||
}
|
}
|
||||||
@@ -335,12 +337,12 @@ class MeekroDB {
|
|||||||
if (isset($options['update']) && is_array($options['update']) && $options['update'] && strtolower($which) == 'insert') {
|
if (isset($options['update']) && is_array($options['update']) && $options['update'] && strtolower($which) == 'insert') {
|
||||||
if (array_values($options['update']) !== $options['update']) {
|
if (array_values($options['update']) !== $options['update']) {
|
||||||
return $this->query(
|
return $this->query(
|
||||||
str_replace('%', $this->param_char, "INSERT INTO %b %lb VALUES %? ON DUPLICATE KEY UPDATE %?"),
|
str_replace('%', $this->param_char, "INSERT INTO %b %lb VALUES $var ON DUPLICATE KEY UPDATE %hc"),
|
||||||
$table, $keys, $values, $options['update']);
|
$table, $keys, $values, $options['update']);
|
||||||
} else {
|
} else {
|
||||||
$update_str = array_shift($options['update']);
|
$update_str = array_shift($options['update']);
|
||||||
$query_param = array(
|
$query_param = array(
|
||||||
str_replace('%', $this->param_char, "INSERT INTO %b %lb VALUES %? ON DUPLICATE KEY UPDATE ") . $update_str,
|
str_replace('%', $this->param_char, "INSERT INTO %b %lb VALUES $var ON DUPLICATE KEY UPDATE ") . $update_str,
|
||||||
$table, $keys, $values);
|
$table, $keys, $values);
|
||||||
$query_param = array_merge($query_param, $options['update']);
|
$query_param = array_merge($query_param, $options['update']);
|
||||||
return call_user_func_array(array($this, 'query'), $query_param);
|
return call_user_func_array(array($this, 'query'), $query_param);
|
||||||
@@ -349,7 +351,7 @@ class MeekroDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $this->query(
|
return $this->query(
|
||||||
str_replace('%', $this->param_char, "%l INTO %b %lb VALUES %?"),
|
str_replace('%', $this->param_char, "%l INTO %b %lb VALUES $var"),
|
||||||
$which, $table, $keys, $values);
|
$which, $table, $keys, $values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,6 +432,11 @@ class MeekroDB {
|
|||||||
$this->param_char . 'b', // backtick
|
$this->param_char . 'b', // backtick
|
||||||
$this->param_char . 't', // timestamp
|
$this->param_char . 't', // timestamp
|
||||||
$this->param_char . '?', // infer type
|
$this->param_char . '?', // infer type
|
||||||
|
$this->param_char . 'l?', // list of inferred types
|
||||||
|
$this->param_char . 'll?', // list of lists of inferred types
|
||||||
|
$this->param_char . 'hc', // hash `key`='value' pairs separated by commas
|
||||||
|
$this->param_char . 'ha', // hash `key`='value' pairs separated by and
|
||||||
|
$this->param_char . 'ho', // hash `key`='value' pairs separated by or
|
||||||
$this->param_char . 'ss' // search string (like string, surrounded with %'s)
|
$this->param_char . 'ss' // search string (like string, surrounded with %'s)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -503,33 +510,53 @@ class MeekroDB {
|
|||||||
|
|
||||||
public function escape($str) { return "'" . $this->get()->real_escape_string(strval($str)) . "'"; }
|
public function escape($str) { return "'" . $this->get()->real_escape_string(strval($str)) . "'"; }
|
||||||
|
|
||||||
public function sanitize($value) {
|
protected function sanitize($value, $type='basic', $hashjoin=', ') {
|
||||||
if (is_object($value)) {
|
if ($type == 'basic') {
|
||||||
if ($value instanceof MeekroDBEval) return $value->text;
|
if (is_object($value)) {
|
||||||
else if ($value instanceof DateTime) return $this->escape($value->format('Y-m-d H:i:s'));
|
if ($value instanceof MeekroDBEval) return $value->text;
|
||||||
else return '';
|
else if ($value instanceof DateTime) return $this->escape($value->format('Y-m-d H:i:s'));
|
||||||
}
|
else return '';
|
||||||
|
|
||||||
if (is_null($value)) return $this->usenull ? 'NULL' : "''";
|
|
||||||
else if (is_bool($value)) return ($value ? 1 : 0);
|
|
||||||
else if (is_int($value)) return $value;
|
|
||||||
else if (is_float($value)) return $value;
|
|
||||||
|
|
||||||
else if (is_array($value)) {
|
|
||||||
// non-assoc array?
|
|
||||||
if (array_values($value) === $value) {
|
|
||||||
if (is_array($value[0])) return implode(', ', array_map(array($this, 'sanitize'), $value));
|
|
||||||
else return '(' . implode(', ', array_map(array($this, 'sanitize'), $value)) . ')';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$pairs = array();
|
if (is_null($value)) return $this->usenull ? 'NULL' : "''";
|
||||||
foreach ($value as $k => $v) {
|
else if (is_bool($value)) return ($value ? 1 : 0);
|
||||||
$pairs[] = $this->formatTableName($k) . '=' . $this->sanitize($v);
|
else if (is_int($value)) return $value;
|
||||||
|
else if (is_float($value)) return $value;
|
||||||
|
else if (is_array($value)) return "''";
|
||||||
|
else return $this->escape($value);
|
||||||
|
|
||||||
|
} else if ($type == 'list') {
|
||||||
|
if (is_array($value) && array_values($value) === $value) {
|
||||||
|
return '(' . implode(', ', array_map(array($this, 'sanitize'), $value)) . ')';
|
||||||
|
} else {
|
||||||
|
return $this->nonSQLError("Expected array parameter, got something different!");
|
||||||
}
|
}
|
||||||
|
} else if ($type == 'doublelist') {
|
||||||
return implode(', ', $pairs);
|
if (is_array($value) && array_values($value) === $value && is_array($value[0])) {
|
||||||
|
$cleanvalues = array();
|
||||||
|
foreach ($value as $subvalue) {
|
||||||
|
$cleanvalues[] = $this->sanitize($subvalue, 'list');
|
||||||
|
}
|
||||||
|
return implode(', ', $cleanvalues);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return $this->nonSQLError("Expected double array parameter, got something different!");
|
||||||
|
}
|
||||||
|
} else if ($type == 'hash') {
|
||||||
|
if (is_array($value) && array_values($value) !== $value) {
|
||||||
|
$pairs = array();
|
||||||
|
foreach ($value as $k => $v) {
|
||||||
|
$pairs[] = $this->formatTableName($k) . '=' . $this->sanitize($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode($hashjoin, $pairs);
|
||||||
|
} else {
|
||||||
|
return $this->nonSQLError("Expected hash (associative array) parameter, got something different!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $this->nonSQLError("Invalid type passed to sanitize()!");
|
||||||
}
|
}
|
||||||
else return $this->escape($value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function parseTS($ts) {
|
protected function parseTS($ts) {
|
||||||
@@ -547,7 +574,7 @@ class MeekroDB {
|
|||||||
$chunkyQuery = call_user_func_array(array($this, 'preparseQueryParams'), $args);
|
$chunkyQuery = call_user_func_array(array($this, 'preparseQueryParams'), $args);
|
||||||
|
|
||||||
$query = '';
|
$query = '';
|
||||||
$array_types = array('ls', 'li', 'ld', 'lb', 'll', 'lt');
|
$array_types = array('ls', 'li', 'ld', 'lb', 'll', 'lt', 'l?', 'll?', 'hc', 'ha', 'ho');
|
||||||
|
|
||||||
foreach ($chunkyQuery as $chunk) {
|
foreach ($chunkyQuery as $chunk) {
|
||||||
if (is_string($chunk)) {
|
if (is_string($chunk)) {
|
||||||
@@ -559,11 +586,9 @@ class MeekroDB {
|
|||||||
$arg = $chunk['value'];
|
$arg = $chunk['value'];
|
||||||
$result = '';
|
$result = '';
|
||||||
|
|
||||||
if ($type != '?') {
|
$is_array_type = in_array($type, $array_types, true);
|
||||||
$is_array_type = in_array($type, $array_types, true);
|
if ($is_array_type && !is_array($arg)) return $this->nonSQLError("Badly formatted SQL query: Expected array, got scalar instead!");
|
||||||
if ($is_array_type && !is_array($arg)) return $this->nonSQLError("Badly formatted SQL query: Expected array, got scalar instead!");
|
else if (!$is_array_type && is_array($arg)) $arg = '';
|
||||||
else if (!$is_array_type && is_array($arg)) return $this->nonSQLError("Badly formatted SQL query: Expected scalar, got array instead!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($type == 's') $result = $this->escape($arg);
|
if ($type == 's') $result = $this->escape($arg);
|
||||||
else if ($type == 'i') $result = $this->intval($arg);
|
else if ($type == 'i') $result = $this->intval($arg);
|
||||||
@@ -581,6 +606,11 @@ class MeekroDB {
|
|||||||
else if ($type == 'lt') $result = array_map(array($this, 'escape'), array_map(array($this, 'parseTS'), $arg));
|
else if ($type == 'lt') $result = array_map(array($this, 'escape'), array_map(array($this, 'parseTS'), $arg));
|
||||||
|
|
||||||
else if ($type == '?') $result = $this->sanitize($arg);
|
else if ($type == '?') $result = $this->sanitize($arg);
|
||||||
|
else if ($type == 'l?') $result = $this->sanitize($arg, 'list');
|
||||||
|
else if ($type == 'll?') $result = $this->sanitize($arg, 'doublelist');
|
||||||
|
else if ($type == 'hc') $result = $this->sanitize($arg, 'hash');
|
||||||
|
else if ($type == 'ha') $result = $this->sanitize($arg, 'hash', ' AND ');
|
||||||
|
else if ($type == 'ho') $result = $this->sanitize($arg, 'hash', ' OR ');
|
||||||
|
|
||||||
else return $this->nonSQLError("Badly formatted SQL query: Invalid MeekroDB param $type");
|
else return $this->nonSQLError("Badly formatted SQL query: Invalid MeekroDB param $type");
|
||||||
|
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ class BasicTest extends SimpleTest {
|
|||||||
'height' => 199.194
|
'height' => 199.194
|
||||||
));
|
));
|
||||||
|
|
||||||
$ct = DB::queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s AND height=%d", 'gonesoon', 199.194);
|
$ct = DB::queryFirstField("SELECT COUNT(*) FROM accounts WHERE %ha", array('username' => 'gonesoon', 'height' => 199.194));
|
||||||
$this->assert(intval($ct) === 1);
|
$this->assert(intval($ct) === 1);
|
||||||
|
|
||||||
$ct = DB::queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s1 AND height=%d0 AND height=%d", 199.194, 'gonesoon');
|
$ct = DB::queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s1 AND height=%d0 AND height=%d", 199.194, 'gonesoon');
|
||||||
|
|||||||
Reference in New Issue
Block a user