From 6f371499d3062ed26d2e0faee54c3146a0780a1c Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Mon, 1 Apr 2024 01:50:24 +0200 Subject: [PATCH] Improved special character handling in manticore and URL query. --- components/filters/filters.vue | 2 +- pages/tags/+Page.vue | 1 + src/actors.js | 5 +++-- src/api.js | 2 +- src/navigate.js | 2 +- src/scenes.js | 6 +++--- utils/escape-manticore.js | 11 +++++++++++ 7 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 utils/escape-manticore.js diff --git a/components/filters/filters.vue b/components/filters/filters.vue index d7bb8bd..add5bdd 100644 --- a/components/filters/filters.vue +++ b/components/filters/filters.vue @@ -283,7 +283,7 @@ function toggleFilters(state) { width: 1.75rem; display: flex; align-items: center; - justify-content: center; + justify-content: flex-end; padding: 0 .25rem; overflow: hidden; color: var(--shadow-weak-10); diff --git a/pages/tags/+Page.vue b/pages/tags/+Page.vue index 5f28e1b..b99dcff 100644 --- a/pages/tags/+Page.vue +++ b/pages/tags/+Page.vue @@ -46,6 +46,7 @@ (value === undefined ? null : [key, value])).filter(Boolean)); - return `?${encodeURI(decodeURIComponent(new URLSearchParams(curatedQuery).toString()))}`; // recode so commas aren't encoded + return `?${new URLSearchParams(curatedQuery).toString()}`; // recode so commas aren't encoded } function showFeedback(isSuccess, options = {}, errorMessage) { diff --git a/src/navigate.js b/src/navigate.js index 9614440..c02160d 100644 --- a/src/navigate.js +++ b/src/navigate.js @@ -9,7 +9,7 @@ export default function navigate(path, query, options = {}) { }).toString(); const url = queryString - ? `${path}?${encodeURI(decodeURIComponent(queryString))}` // URLSearchParams encodes commas, we don't want that + ? `${path}?${queryString.replace(/%2C/g, ',')}` // URLSearchParams encodes commas, we don't want that : path; if (options.redirect) { diff --git a/src/scenes.js b/src/scenes.js index 40aa14e..cc69ae4 100644 --- a/src/scenes.js +++ b/src/scenes.js @@ -8,6 +8,7 @@ import { fetchActorsById, curateActor, sortActorsByGender } from './actors.js'; import { fetchTagsById } from './tags.js'; import { fetchEntitiesById } from './entities.js'; import { curateStash } from './stashes.js'; +import escape from '../utils/escape-manticore.js'; import promiseProps from '../utils/promise-props.js'; function curateMedia(media) { @@ -428,7 +429,7 @@ async function queryManticoreSql(filters, options, _reqUser) { } if (filters.query) { - builder.whereRaw('match(\'@!title :query:\', scenes)', { query: filters.query }); + builder.whereRaw('match(\'@!title :query:\', scenes)', { query: escape(filters.query) }); } filters.tagIds?.forEach((tagId) => { @@ -492,8 +493,7 @@ async function queryManticoreSql(filters, options, _reqUser) { } }) .limit(options.limit) - .offset((options.page - 1) * options.limit) - .toString(), + .offset((options.page - 1) * options.limit), // option threads=1 fixes actors, but drastically slows down performance, wait for fix actorsFacet: options.aggregateActors ? knex.raw('facet scenes.actor_ids order by count(*) desc limit ?', [aggSize]) : null, tagsFacet: options.aggregateTags ? knex.raw('facet scenes.tag_ids order by count(*) desc limit ?', [aggSize]) : null, diff --git a/utils/escape-manticore.js b/utils/escape-manticore.js new file mode 100644 index 0000000..a6a275b --- /dev/null +++ b/utils/escape-manticore.js @@ -0,0 +1,11 @@ +// https://manual.manticoresearch.com/Searching/Full_text_matching/Escaping#Escaping-characters-in-query-string +export default function escape(string) { + if (!string) { + return null; + } + + return string + .replace(/\\/g, String.raw`\\\\`) // using String.raw so we don't have to double up JS and SQL escaping + .replace(/'/g, String.raw`\'`) + .replace(/(["!$()/<@^|~-])/g, String.raw`\\$1`); +}