From 5047cf10276717ebed7093c9ca8c8be5dafe88b5 Mon Sep 17 00:00:00 2001 From: Roman Musin Date: Thu, 24 Jun 2021 12:24:03 +0000 Subject: [PATCH 1/2] Android: Disable backup to Google Drive (#5114) Ref: https://discourse.joplinapp.org/t/cant-do-a-clean-re-install-on-android-using-joplin-cloud --- packages/app-mobile/android/app/src/main/AndroidManifest.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/app-mobile/android/app/src/main/AndroidManifest.xml b/packages/app-mobile/android/app/src/main/AndroidManifest.xml index 1b420c8b9..ec39f305e 100644 --- a/packages/app-mobile/android/app/src/main/AndroidManifest.xml +++ b/packages/app-mobile/android/app/src/main/AndroidManifest.xml @@ -18,9 +18,6 @@ Apps targeting Android 10 (sdk 29) can no longer freely access arbitrary paths on the shared storage. This attribute allows to opt out of this restriction. - android:allowBackup: used to enable Android Backup which some users need: - https://github.com/laurent22/joplin/issues/4020 - android:resizeableActivity: allows user to resize Joplin window https://github.com/laurent22/joplin/issues/3547 --> @@ -29,7 +26,7 @@ android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" - android:allowBackup="true" + android:allowBackup="false" android:networkSecurityConfig="@xml/network_security_config" android:requestLegacyExternalStorage="true" android:resizeableActivity="true" From 8cbcb78ad109a65baf04d817780c6dda427ed110 Mon Sep 17 00:00:00 2001 From: JackGruber <24863925+JackGruber@users.noreply.github.com> Date: Thu, 24 Jun 2021 14:24:54 +0200 Subject: [PATCH 2/2] All: Resolves #3871: Interpret only valid search filters (#5103) --- .eslintignore | 3 +++ .gitignore | 3 +++ README.md | 2 ++ ...lterParser.test.js => filterParser.test.ts} | 18 +++++++++--------- .../lib/services/searchengine/filterParser.ts | 7 ++++--- 5 files changed, 21 insertions(+), 12 deletions(-) rename packages/lib/services/searchengine/{filterParser.test.js => filterParser.test.ts} (89%) diff --git a/.eslintignore b/.eslintignore index 14588a0ff..e1986ea51 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1397,6 +1397,9 @@ packages/lib/services/searchengine/SearchEngineUtils.test.js.map packages/lib/services/searchengine/filterParser.d.ts packages/lib/services/searchengine/filterParser.js packages/lib/services/searchengine/filterParser.js.map +packages/lib/services/searchengine/filterParser.test.d.ts +packages/lib/services/searchengine/filterParser.test.js +packages/lib/services/searchengine/filterParser.test.js.map packages/lib/services/searchengine/queryBuilder.d.ts packages/lib/services/searchengine/queryBuilder.js packages/lib/services/searchengine/queryBuilder.js.map diff --git a/.gitignore b/.gitignore index 08bcc7ef0..44d1406c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1383,6 +1383,9 @@ packages/lib/services/searchengine/SearchEngineUtils.test.js.map packages/lib/services/searchengine/filterParser.d.ts packages/lib/services/searchengine/filterParser.js packages/lib/services/searchengine/filterParser.js.map +packages/lib/services/searchengine/filterParser.test.d.ts +packages/lib/services/searchengine/filterParser.test.js +packages/lib/services/searchengine/filterParser.test.js.map packages/lib/services/searchengine/queryBuilder.d.ts packages/lib/services/searchengine/queryBuilder.js packages/lib/services/searchengine/queryBuilder.js.map diff --git a/README.md b/README.md index 8f33cc15c..600c17200 100644 --- a/README.md +++ b/README.md @@ -453,6 +453,8 @@ The filters are implicitly connected by and/or connectives depending on the foll - To override this default behaviour, use the `any` filter, in which case the search terms will be connected by "OR" instead. - There's an exception for the `notebook` filters which are connected by "OR". The reason being that no note can be in multiple notebooks at once. +Incorrect search filters are interpreted as a phrase search, e.g. misspelled `nootebook:Example` or non-existing `https://joplinapp.org`. + ## Search order Notes are sorted by "relevance". Currently it means the notes that contain the requested terms the most times are on top. For queries with multiple terms, it also matters how close to each other the terms are. This is a bit experimental so if you notice a search query that returns unexpected results, please report it in the forum, providing as many details as possible to replicate the issue. diff --git a/packages/lib/services/searchengine/filterParser.test.js b/packages/lib/services/searchengine/filterParser.test.ts similarity index 89% rename from packages/lib/services/searchengine/filterParser.test.js rename to packages/lib/services/searchengine/filterParser.test.ts index 36f0b70e5..84f1c4f4d 100644 --- a/packages/lib/services/searchengine/filterParser.test.js +++ b/packages/lib/services/searchengine/filterParser.test.ts @@ -1,11 +1,8 @@ -/* eslint-disable no-unused-vars */ +import filterParser from './filterParser'; -const filterParser = require('../../services/searchengine/filterParser.js').default; -// import filterParser from '../../services/searchengine/filterParser.js'; - -const makeTerm = (name, value, negated, quoted = false, wildcard = false) => { +const makeTerm = (name: string, value: string, negated: boolean, quoted: boolean = false, wildcard: boolean = false) => { if (name === 'text') { return { name, value, negated, quoted, wildcard }; } - if (name === 'title' | name === 'body') { return { name, value, negated, wildcard }; } + if (name === 'title' || name === 'body') { return { name, value, negated, wildcard }; } return { name, value, negated }; }; @@ -135,13 +132,16 @@ describe('filterParser should be correct filter for keyword', () => { it('handle invalid filters', () => { let searchString = 'titletitle:123'; - expect(() => filterParser(searchString)).toThrow(new Error('Invalid filter: titletitle')); + expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"titletitle:123"', false)); searchString = 'invalid:abc'; - expect(() => filterParser(searchString)).toThrow(new Error('Invalid filter: invalid')); + expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"invalid:abc"', false)); + + searchString = '-invalid:abc'; + expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"invalid:abc"', true)); searchString = ':abc'; - expect(() => filterParser(searchString)).toThrow(new Error('Invalid filter: ')); + expect(filterParser(searchString)).toContainEqual(makeTerm('text', '":abc"', false)); searchString = 'type:blah'; expect(() => filterParser(searchString)).toThrow(new Error('The value of filter "type" must be "note" or "todo"')); diff --git a/packages/lib/services/searchengine/filterParser.ts b/packages/lib/services/searchengine/filterParser.ts index e6ffc456c..b1dd8dddf 100644 --- a/packages/lib/services/searchengine/filterParser.ts +++ b/packages/lib/services/searchengine/filterParser.ts @@ -22,7 +22,7 @@ const quote = (s: string) => { }; -const getTerms = (query: string): Term[] => { +const getTerms = (query: string, validFilters: Set): Term[] => { const terms: Term[] = []; let inQuote = false; let inTerm = false; @@ -52,7 +52,8 @@ const getTerms = (query: string): Term[] => { continue; } - if (c === ':' && !inQuote && !inTerm) { + if (c === ':' && !inQuote && !inTerm && + (validFilters.has(currentTerm) || currentTerm[0] === '-' && validFilters.has(currentTerm.substr(1, currentTerm.length)))) { currentCol = currentTerm; currentTerm = ''; inTerm = true; // to ignore any other ':' before a space eg.'sourceurl:https://www.google.com' @@ -71,7 +72,7 @@ const parseQuery = (query: string): Term[] => { 'iscompleted', 'due', 'latitude', 'longitude', 'altitude', 'resource', 'sourceurl', 'id']); - const terms = getTerms(query); + const terms = getTerms(query, validFilters); const result: Term[] = []; for (let i = 0; i < terms.length; i++) {