Skip to content

Commit e83536f

Browse files
committed
Fix mistic100#929 escaping of raw SQL
1 parent b6160dc commit e83536f

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

src/plugins/sql-support/plugin.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ QueryBuilder.defaults({
2424
greater_or_equal: { op: '>= ?' },
2525
between: { op: 'BETWEEN ?', sep: ' AND ' },
2626
not_between: { op: 'NOT BETWEEN ?', sep: ' AND ' },
27-
begins_with: { op: 'LIKE(?)', mod: '{0}%' },
28-
not_begins_with: { op: 'NOT LIKE(?)', mod: '{0}%' },
29-
contains: { op: 'LIKE(?)', mod: '%{0}%' },
30-
not_contains: { op: 'NOT LIKE(?)', mod: '%{0}%' },
31-
ends_with: { op: 'LIKE(?)', mod: '%{0}' },
32-
not_ends_with: { op: 'NOT LIKE(?)', mod: '%{0}' },
27+
begins_with: { op: 'LIKE ?', mod: '{0}%', escape: '%_' },
28+
not_begins_with: { op: 'NOT LIKE ?', mod: '{0}%', escape: '%_' },
29+
contains: { op: 'LIKE ?', mod: '%{0}%', escape: '%_' },
30+
not_contains: { op: 'NOT LIKE ?', mod: '%{0}%', escape: '%_' },
31+
ends_with: { op: 'LIKE ?', mod: '%{0}', escape: '%_' },
32+
not_ends_with: { op: 'NOT LIKE ?', mod: '%{0}', escape: '%_' },
3333
is_empty: { op: '= \'\'' },
3434
is_not_empty: { op: '!= \'\'' },
3535
is_null: { op: 'IS NULL' },
@@ -307,7 +307,7 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ {
307307
v = v ? 1 : 0;
308308
}
309309
else if (!stmt && rule.type !== 'integer' && rule.type !== 'double' && rule.type !== 'boolean') {
310-
v = Utils.escapeString(v);
310+
v = Utils.escapeString(v, sql.escape);
311311
}
312312

313313
if (sql.mod) {
@@ -579,6 +579,19 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ {
579579
Utils.error('SQLParse', 'Cannot find field name in {0}', JSON.stringify(data.left));
580580
}
581581

582+
// unescape chars declared by the operator
583+
var finalValue = opVal.val;
584+
var sql = self.settings.sqlOperators[opVal.op];
585+
if (!stmt && sql && sql.escape) {
586+
var searchChars = sql.escape.split('').map(function(c) {
587+
return '\\\\' + c;
588+
}).join('|');
589+
finalValue = finalValue
590+
.replace(new RegExp('(' + searchChars + ')', 'g'), function(s) {
591+
return s[1];
592+
});
593+
}
594+
582595
var id = self.getSQLFieldID(field, value);
583596

584597
/**
@@ -593,7 +606,7 @@ QueryBuilder.extend(/** @lends module:plugins.SqlSupport.prototype */ {
593606
id: id,
594607
field: field,
595608
operator: opVal.op,
596-
value: opVal.val
609+
value: finalValue
597610
}, data);
598611

599612
curr.rules.push(rule);

src/utils.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,28 +145,39 @@ Utils.changeType = function(value, type) {
145145
/**
146146
* Escapes a string like PHP's mysql_real_escape_string does
147147
* @param {string} value
148+
* @param {string} [additionalEscape] additionnal chars to escape
148149
* @returns {string}
149150
*/
150-
Utils.escapeString = function(value) {
151+
Utils.escapeString = function(value, additionalEscape) {
151152
if (typeof value != 'string') {
152153
return value;
153154
}
154155

155-
return value
156+
var escaped = value
156157
.replace(/[\0\n\r\b\\\'\"]/g, function(s) {
157158
switch (s) {
158159
// @formatter:off
159160
case '\0': return '\\0';
160161
case '\n': return '\\n';
161162
case '\r': return '\\r';
162163
case '\b': return '\\b';
164+
case '\'': return '\'\'';
163165
default: return '\\' + s;
164166
// @formatter:off
165167
}
166168
})
167169
// uglify compliant
168170
.replace(/\t/g, '\\t')
169171
.replace(/\x1a/g, '\\Z');
172+
173+
if (additionalEscape) {
174+
escaped = escaped
175+
.replace(new RegExp('[' + additionalEscape + ']', 'g'), function(s) {
176+
return '\\' + s;
177+
});
178+
}
179+
180+
return escaped;
170181
};
171182

172183
/**

0 commit comments

Comments
 (0)