mirror of
https://github.com/crmeb/CRMEB.git
synced 2025-12-20 01:12:50 +00:00
tp5 漏洞修复
This commit is contained in:
parent
322b7d463e
commit
23aafa1a17
@ -2,7 +2,7 @@
|
|||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
|
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
// +----------------------------------------------------------------------
|
// +----------------------------------------------------------------------
|
||||||
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
namespace think\db;
|
namespace think\db;
|
||||||
|
|
||||||
use BadMethodCallException;
|
|
||||||
use PDO;
|
use PDO;
|
||||||
use think\Exception;
|
use think\Exception;
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ abstract class Builder
|
|||||||
protected $exp = ['eq' => '=', 'neq' => '<>', 'gt' => '>', 'egt' => '>=', 'lt' => '<', 'elt' => '<=', 'notlike' => 'NOT LIKE', 'not like' => 'NOT LIKE', 'like' => 'LIKE', 'in' => 'IN', 'exp' => 'EXP', 'notin' => 'NOT IN', 'not in' => 'NOT IN', 'between' => 'BETWEEN', 'not between' => 'NOT BETWEEN', 'notbetween' => 'NOT BETWEEN', 'exists' => 'EXISTS', 'notexists' => 'NOT EXISTS', 'not exists' => 'NOT EXISTS', 'null' => 'NULL', 'notnull' => 'NOT NULL', 'not null' => 'NOT NULL', '> time' => '> TIME', '< time' => '< TIME', '>= time' => '>= TIME', '<= time' => '<= TIME', 'between time' => 'BETWEEN TIME', 'not between time' => 'NOT BETWEEN TIME', 'notbetween time' => 'NOT BETWEEN TIME'];
|
protected $exp = ['eq' => '=', 'neq' => '<>', 'gt' => '>', 'egt' => '>=', 'lt' => '<', 'elt' => '<=', 'notlike' => 'NOT LIKE', 'not like' => 'NOT LIKE', 'like' => 'LIKE', 'in' => 'IN', 'exp' => 'EXP', 'notin' => 'NOT IN', 'not in' => 'NOT IN', 'between' => 'BETWEEN', 'not between' => 'NOT BETWEEN', 'notbetween' => 'NOT BETWEEN', 'exists' => 'EXISTS', 'notexists' => 'NOT EXISTS', 'not exists' => 'NOT EXISTS', 'null' => 'NULL', 'notnull' => 'NOT NULL', 'not null' => 'NOT NULL', '> time' => '> TIME', '< time' => '< TIME', '>= time' => '>= TIME', '<= time' => '<= TIME', 'between time' => 'BETWEEN TIME', 'not between time' => 'NOT BETWEEN TIME', 'notbetween time' => 'NOT BETWEEN TIME'];
|
||||||
|
|
||||||
// SQL表达式
|
// SQL表达式
|
||||||
protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%LOCK%%COMMENT%';
|
protected $selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%FORCE%%JOIN%%WHERE%%GROUP%%HAVING%%UNION%%ORDER%%LIMIT%%LOCK%%COMMENT%';
|
||||||
protected $insertSql = '%INSERT% INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT%';
|
protected $insertSql = '%INSERT% INTO %TABLE% (%FIELD%) VALUES (%DATA%) %COMMENT%';
|
||||||
protected $insertAllSql = '%INSERT% INTO %TABLE% (%FIELD%) %DATA% %COMMENT%';
|
protected $insertAllSql = '%INSERT% INTO %TABLE% (%FIELD%) %DATA% %COMMENT%';
|
||||||
protected $updateSql = 'UPDATE %TABLE% SET %SET% %JOIN% %WHERE% %ORDER%%LIMIT% %LOCK%%COMMENT%';
|
protected $updateSql = 'UPDATE %TABLE% SET %SET% %JOIN% %WHERE% %ORDER%%LIMIT% %LOCK%%COMMENT%';
|
||||||
@ -99,8 +98,11 @@ abstract class Builder
|
|||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($data as $key => $val) {
|
foreach ($data as $key => $val) {
|
||||||
$item = $this->parseKey($key, $options);
|
$item = $this->parseKey($key, $options, true);
|
||||||
if (is_object($val) && method_exists($val, '__toString')) {
|
if ($val instanceof Expression) {
|
||||||
|
$result[$item] = $val->getValue();
|
||||||
|
continue;
|
||||||
|
} elseif (is_object($val) && method_exists($val, '__toString')) {
|
||||||
// 对象数据写入
|
// 对象数据写入
|
||||||
$val = $val->__toString();
|
$val = $val->__toString();
|
||||||
}
|
}
|
||||||
@ -110,8 +112,23 @@ abstract class Builder
|
|||||||
}
|
}
|
||||||
} elseif (is_null($val)) {
|
} elseif (is_null($val)) {
|
||||||
$result[$item] = 'NULL';
|
$result[$item] = 'NULL';
|
||||||
} elseif (isset($val[0]) && 'exp' == $val[0]) {
|
} elseif (is_array($val) && !empty($val)) {
|
||||||
$result[$item] = $val[1];
|
switch (strtolower($val[0])) {
|
||||||
|
case 'inc':
|
||||||
|
//$result[$item] = $item . '+' . floatval($val[1]);
|
||||||
|
if ($key == $val[1]) {
|
||||||
|
$result[$item] = $this->parseKey($val[1]) . '+' . floatval($val[2]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'dec':
|
||||||
|
//$result[$item] = $item . '-' . floatval($val[1]);
|
||||||
|
if ($key == $val[1]) {
|
||||||
|
$result[$item] = $this->parseKey($val[1]) . '-' . floatval($val[2]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'exp':
|
||||||
|
throw new Exception('not support data:[' . $val[0] . ']');
|
||||||
|
}
|
||||||
} elseif (is_scalar($val)) {
|
} elseif (is_scalar($val)) {
|
||||||
// 过滤非标量数据
|
// 过滤非标量数据
|
||||||
if (0 === strpos($val, ':') && $this->query->isBind(substr($val, 1))) {
|
if (0 === strpos($val, ':') && $this->query->isBind(substr($val, 1))) {
|
||||||
@ -133,7 +150,7 @@ abstract class Builder
|
|||||||
* @param array $options
|
* @param array $options
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function parseKey($key, $options = [])
|
protected function parseKey($key, $options = [], $strict = false)
|
||||||
{
|
{
|
||||||
return $key;
|
return $key;
|
||||||
}
|
}
|
||||||
@ -174,8 +191,10 @@ abstract class Builder
|
|||||||
// 支持 'field1'=>'field2' 这样的字段别名定义
|
// 支持 'field1'=>'field2' 这样的字段别名定义
|
||||||
$array = [];
|
$array = [];
|
||||||
foreach ($fields as $key => $field) {
|
foreach ($fields as $key => $field) {
|
||||||
if (!is_numeric($key)) {
|
if ($field instanceof Expression) {
|
||||||
$array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options);
|
$array[] = $field->getValue();
|
||||||
|
} elseif (!is_numeric($key)) {
|
||||||
|
$array[] = $this->parseKey($key, $options) . ' AS ' . $this->parseKey($field, $options, true);
|
||||||
} else {
|
} else {
|
||||||
$array[] = $this->parseKey($field, $options);
|
$array[] = $this->parseKey($field, $options);
|
||||||
}
|
}
|
||||||
@ -197,9 +216,6 @@ abstract class Builder
|
|||||||
$item = [];
|
$item = [];
|
||||||
foreach ((array) $tables as $key => $table) {
|
foreach ((array) $tables as $key => $table) {
|
||||||
if (!is_numeric($key)) {
|
if (!is_numeric($key)) {
|
||||||
if (strpos($key, '@think')) {
|
|
||||||
$key = strstr($key, '@think', true);
|
|
||||||
}
|
|
||||||
$key = $this->parseSqlTable($key);
|
$key = $this->parseSqlTable($key);
|
||||||
$item[] = $this->parseKey($key) . ' ' . (isset($options['alias'][$table]) ? $this->parseKey($options['alias'][$table]) : $this->parseKey($table));
|
$item[] = $this->parseKey($key) . ' ' . (isset($options['alias'][$table]) ? $this->parseKey($options['alias'][$table]) : $this->parseKey($table));
|
||||||
} else {
|
} else {
|
||||||
@ -257,7 +273,9 @@ abstract class Builder
|
|||||||
foreach ($where as $key => $val) {
|
foreach ($where as $key => $val) {
|
||||||
$str = [];
|
$str = [];
|
||||||
foreach ($val as $field => $value) {
|
foreach ($val as $field => $value) {
|
||||||
if ($value instanceof \Closure) {
|
if ($value instanceof Expression) {
|
||||||
|
$str[] = ' ' . $key . ' ( ' . $value->getValue() . ' )';
|
||||||
|
} elseif ($value instanceof \Closure) {
|
||||||
// 使用闭包查询
|
// 使用闭包查询
|
||||||
$query = new Query($this->connection);
|
$query = new Query($this->connection);
|
||||||
call_user_func_array($value, [ & $query]);
|
call_user_func_array($value, [ & $query]);
|
||||||
@ -298,7 +316,7 @@ abstract class Builder
|
|||||||
protected function parseWhereItem($field, $val, $rule = '', $options = [], $binds = [], $bindName = null)
|
protected function parseWhereItem($field, $val, $rule = '', $options = [], $binds = [], $bindName = null)
|
||||||
{
|
{
|
||||||
// 字段分析
|
// 字段分析
|
||||||
$key = $field ? $this->parseKey($field, $options) : '';
|
$key = $field ? $this->parseKey($field, $options, true) : '';
|
||||||
|
|
||||||
// 查询规则和条件
|
// 查询规则和条件
|
||||||
if (!is_array($val)) {
|
if (!is_array($val)) {
|
||||||
@ -331,13 +349,15 @@ abstract class Builder
|
|||||||
throw new Exception('where express error:' . $exp);
|
throw new Exception('where express error:' . $exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$bindName = $bindName ?: 'where_' . str_replace(['.', '-'], '_', $field);
|
$bindName = $bindName ?: 'where_' . $rule . '_' . str_replace(['.', '-'], '_', $field);
|
||||||
if (preg_match('/\W/', $bindName)) {
|
if (preg_match('/\W/', $bindName)) {
|
||||||
// 处理带非单词字符的字段名
|
// 处理带非单词字符的字段名
|
||||||
$bindName = md5($bindName);
|
$bindName = md5($bindName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_object($value) && method_exists($value, '__toString')) {
|
if ($value instanceof Expression) {
|
||||||
|
|
||||||
|
} elseif (is_object($value) && method_exists($value, '__toString')) {
|
||||||
// 对象数据写入
|
// 对象数据写入
|
||||||
$value = $value->__toString();
|
$value = $value->__toString();
|
||||||
}
|
}
|
||||||
@ -374,7 +394,11 @@ abstract class Builder
|
|||||||
}
|
}
|
||||||
} elseif ('EXP' == $exp) {
|
} elseif ('EXP' == $exp) {
|
||||||
// 表达式查询
|
// 表达式查询
|
||||||
$whereStr .= '( ' . $key . ' ' . $value . ' )';
|
if ($value instanceof Expression) {
|
||||||
|
$whereStr .= '( ' . $key . ' ' . $value->getValue() . ' )';
|
||||||
|
} else {
|
||||||
|
throw new Exception('where express error:' . $exp);
|
||||||
|
}
|
||||||
} elseif (in_array($exp, ['NOT NULL', 'NULL'])) {
|
} elseif (in_array($exp, ['NOT NULL', 'NULL'])) {
|
||||||
// NULL 查询
|
// NULL 查询
|
||||||
$whereStr .= $key . ' IS ' . $exp;
|
$whereStr .= $key . ' IS ' . $exp;
|
||||||
@ -492,6 +516,11 @@ abstract class Builder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$bindName = $bindName ?: $key;
|
$bindName = $bindName ?: $key;
|
||||||
|
|
||||||
|
if ($this->query->isBind($bindName)) {
|
||||||
|
$bindName .= '_' . str_replace('.', '_', uniqid('', true));
|
||||||
|
}
|
||||||
|
|
||||||
$this->query->bind($bindName, $value, $bindType);
|
$this->query->bind($bindName, $value, $bindType);
|
||||||
return ':' . $bindName;
|
return ':' . $bindName;
|
||||||
}
|
}
|
||||||
@ -522,7 +551,9 @@ abstract class Builder
|
|||||||
list($table, $type, $on) = $item;
|
list($table, $type, $on) = $item;
|
||||||
$condition = [];
|
$condition = [];
|
||||||
foreach ((array) $on as $val) {
|
foreach ((array) $on as $val) {
|
||||||
if (strpos($val, '=')) {
|
if ($val instanceof Expression) {
|
||||||
|
$condition[] = $val->getValue();
|
||||||
|
} elseif (strpos($val, '=')) {
|
||||||
list($val1, $val2) = explode('=', $val, 2);
|
list($val1, $val2) = explode('=', $val, 2);
|
||||||
$condition[] = $this->parseKey($val1, $options) . '=' . $this->parseKey($val2, $options);
|
$condition[] = $this->parseKey($val1, $options) . '=' . $this->parseKey($val2, $options);
|
||||||
} else {
|
} else {
|
||||||
@ -546,28 +577,29 @@ abstract class Builder
|
|||||||
*/
|
*/
|
||||||
protected function parseOrder($order, $options = [])
|
protected function parseOrder($order, $options = [])
|
||||||
{
|
{
|
||||||
if (is_array($order)) {
|
if (empty($order)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
$array = [];
|
$array = [];
|
||||||
foreach ($order as $key => $val) {
|
foreach ($order as $key => $val) {
|
||||||
if (is_numeric($key)) {
|
if ($val instanceof Expression) {
|
||||||
if ('[rand]' == $val) {
|
$array[] = $val->getValue();
|
||||||
if (method_exists($this, 'parseRand')) {
|
} elseif ('[rand]' == $val) {
|
||||||
$array[] = $this->parseRand();
|
$array[] = $this->parseRand();
|
||||||
} else {
|
} else {
|
||||||
throw new BadMethodCallException('method not exists:' . get_class($this) . '-> parseRand');
|
if (is_numeric($key)) {
|
||||||
}
|
list($key, $sort) = explode(' ', strpos($val, ' ') ? $val : $val . ' ');
|
||||||
} elseif (false === strpos($val, '(')) {
|
|
||||||
$array[] = $this->parseKey($val, $options);
|
|
||||||
} else {
|
} else {
|
||||||
$array[] = $val;
|
$sort = $val;
|
||||||
}
|
}
|
||||||
} else {
|
$sort = strtoupper($sort);
|
||||||
$sort = in_array(strtolower(trim($val)), ['asc', 'desc']) ? ' ' . $val : '';
|
$sort = in_array($sort, ['ASC', 'DESC'], true) ? ' ' . $sort : '';
|
||||||
$array[] = $this->parseKey($key, $options) . ' ' . $sort;
|
$array[] = $this->parseKey($key, $options, true) . $sort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$order = implode(',', $array);
|
$order = implode(',', $array);
|
||||||
}
|
|
||||||
return !empty($order) ? ' ORDER BY ' . $order : '';
|
return !empty($order) ? ' ORDER BY ' . $order : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,6 +633,9 @@ abstract class Builder
|
|||||||
*/
|
*/
|
||||||
protected function parseComment($comment)
|
protected function parseComment($comment)
|
||||||
{
|
{
|
||||||
|
if (false !== strpos($comment, '*/')) {
|
||||||
|
$comment = strstr($comment, '*/', true);
|
||||||
|
}
|
||||||
return !empty($comment) ? ' /* ' . $comment . ' */' : '';
|
return !empty($comment) ? ' /* ' . $comment . ' */' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,12 +665,12 @@ abstract class Builder
|
|||||||
unset($union['type']);
|
unset($union['type']);
|
||||||
foreach ($union as $u) {
|
foreach ($union as $u) {
|
||||||
if ($u instanceof \Closure) {
|
if ($u instanceof \Closure) {
|
||||||
$sql[] = $type . ' ' . $this->parseClosure($u, false);
|
$sql[] = $type . ' ' . $this->parseClosure($u);
|
||||||
} elseif (is_string($u)) {
|
} elseif (is_string($u)) {
|
||||||
$sql[] = $type . ' ' . $this->parseSqlTable($u);
|
$sql[] = $type . ' ( ' . $this->parseSqlTable($u) . ' )';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return implode(' ', $sql);
|
return ' ' . implode(' ', $sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -650,11 +685,7 @@ abstract class Builder
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_array($index)) {
|
return sprintf(" FORCE INDEX ( %s ) ", is_array($index) ? implode(',', $index) : $index);
|
||||||
$index = join(",", $index);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf(" FORCE INDEX ( %s ) ", $index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -749,7 +780,7 @@ abstract class Builder
|
|||||||
$fields = $options['field'];
|
$fields = $options['field'];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($dataSet as &$data) {
|
foreach ($dataSet as $data) {
|
||||||
foreach ($data as $key => $val) {
|
foreach ($data as $key => $val) {
|
||||||
if (!in_array($key, $fields, true)) {
|
if (!in_array($key, $fields, true)) {
|
||||||
if ($options['strict']) {
|
if ($options['strict']) {
|
||||||
@ -770,19 +801,25 @@ abstract class Builder
|
|||||||
}
|
}
|
||||||
$value = array_values($data);
|
$value = array_values($data);
|
||||||
$values[] = 'SELECT ' . implode(',', $value);
|
$values[] = 'SELECT ' . implode(',', $value);
|
||||||
|
|
||||||
|
if (!isset($insertFields)) {
|
||||||
|
$insertFields = array_keys($data);
|
||||||
}
|
}
|
||||||
$fields = array_map([$this, 'parseKey'], array_keys(reset($dataSet)));
|
}
|
||||||
$sql = str_replace(
|
|
||||||
|
foreach ($insertFields as $field) {
|
||||||
|
$fields[] = $this->parseKey($field, $options, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_replace(
|
||||||
['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
|
['%INSERT%', '%TABLE%', '%FIELD%', '%DATA%', '%COMMENT%'],
|
||||||
[
|
[
|
||||||
$replace ? 'REPLACE' : 'INSERT',
|
$replace ? 'REPLACE' : 'INSERT',
|
||||||
$this->parseTable($options['table'], $options),
|
$this->parseTable($options['table'], $options),
|
||||||
implode(' , ', $fields),
|
implode(' , ', $insertFields),
|
||||||
implode(' UNION ALL ', $values),
|
implode(' UNION ALL ', $values),
|
||||||
$this->parseComment($options['comment']),
|
$this->parseComment($options['comment']),
|
||||||
], $this->insertAllSql);
|
], $this->insertAllSql);
|
||||||
|
|
||||||
return $sql;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user