diff --git a/chrome/content/zotero/xpcom/utilities_internal.js b/chrome/content/zotero/xpcom/utilities_internal.js index b195f7ff87..cf2f7fd1ea 100644 --- a/chrome/content/zotero/xpcom/utilities_internal.js +++ b/chrome/content/zotero/xpcom/utilities_internal.js @@ -1164,6 +1164,15 @@ Zotero.Utilities.Internal = { }, + /** + * Escape '_', '%', and '\' in an SQL LIKE expression so that it can be used with ESCAPE '\' to + * prevent the wildcards from having special meaning + */ + escapeSQLExpression: function (expr) { + return expr.replace(/([_%\\])/g, '\\$1'); + }, + + buildLibraryMenu: function (menulist, libraries, selectedLibraryID) { var menupopup = menulist.firstChild; while (menupopup.hasChildNodes()) { diff --git a/components/zotero-autocomplete.js b/components/zotero-autocomplete.js index d7ba672e48..60c3773a23 100644 --- a/components/zotero-autocomplete.js +++ b/components/zotero-autocomplete.js @@ -71,8 +71,8 @@ ZoteroAutoComplete.prototype.startSearch = Zotero.Promise.coroutine(function* (s break; case 'tag': - var sql = "SELECT DISTINCT name AS val, NULL AS comment FROM tags WHERE name LIKE ?"; - var sqlParams = [searchString + '%']; + var sql = "SELECT DISTINCT name AS val, NULL AS comment FROM tags WHERE name LIKE ? ESCAPE '\\'"; + var sqlParams = [Zotero.Utilities.Internal.escapeSQLExpression(searchString) + '%']; if (searchParams.libraryID !== undefined) { sql += " AND tagID IN (SELECT tagID FROM itemTags JOIN items USING (itemID) " + "WHERE libraryID=?)";