Search treats % and _ as themselves (#296)
The changelog lines for #292, #293 and #295 ride along in this commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,10 +40,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Artwork a publisher sends without an image type, or as `application/octet-stream`, is shown when it is a JPEG, PNG, GIF or WebP, instead of initials (#279).
|
- Artwork a publisher sends without an image type, or as `application/octet-stream`, is shown when it is a JPEG, PNG, GIF or WebP, instead of initials (#279).
|
||||||
- A 429 from TypeSafe holds every call back as it asks, instead of the pass going on asking (#277).
|
- A 429 from TypeSafe holds every call back as it asks, instead of the pass going on asking (#277).
|
||||||
- Looking for items to read for Signals read every item on the server on each scan; it now reads only recent ones (#274).
|
- Looking for items to read for Signals read every item on the server on each scan; it now reads only recent ones (#274).
|
||||||
|
- With the downloads folder out of reach during a clean-up, as when the array stops, every downloaded episode was taken as deleted by hand and forgotten; the clean-up now leaves them alone until the folder is back (#293).
|
||||||
|
- A feed address that serves something larger than 50 MB, such as an episode's file given as a feed, is refused as too large, instead of read whole into memory at every check (#295).
|
||||||
|
- Searching items for `%` or `_` finds those characters, instead of treating them as wildcards that matched nearly everything (#296).
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
- ammonia, which cleans publishers' HTML, updated to 4.2.4 for three advisories, among them XSS through SVG animation tags; rustls to 0.23.46 for five and h2 to 0.4.20 for one, in every connection ipx makes (#281).
|
- ammonia, which cleans publishers' HTML, updated to 4.2.4 for three advisories, among them XSS through SVG animation tags; rustls to 0.23.46 for five and h2 to 0.4.20 for one, in every connection ipx makes (#281).
|
||||||
|
- The address of a file being downloaded, which for Patreon carries its signature, is sent to open pages and written to the log without its query, as other addresses already were (#292).
|
||||||
|
|
||||||
## [1.3.0] - 2026-10-16
|
## [1.3.0] - 2026-10-16
|
||||||
|
|
||||||
|
|||||||
@@ -1222,8 +1222,13 @@ fn entries_from(
|
|||||||
}
|
}
|
||||||
let search = match search.map(|q| q.trim().to_lowercase()).filter(|q| !q.is_empty()) {
|
let search = match search.map(|q| q.trim().to_lowercase()).filter(|q| !q.is_empty()) {
|
||||||
Some(q) => {
|
Some(q) => {
|
||||||
|
// % and _ as typed, not as wildcards: "100%" matched anything starting 100 (#296).
|
||||||
|
let q = q.replace('\\', "\\\\").replace('%', "\\%").replace('_', "\\_");
|
||||||
let like = a.p(format!("%{q}%"));
|
let like = a.p(format!("%{q}%"));
|
||||||
format!("(lower(coalesce(e.title, '')) LIKE {like} OR lower(coalesce(e.description, '')) LIKE {like})")
|
format!(
|
||||||
|
"(lower(coalesce(e.title, '')) LIKE {like} ESCAPE '\\' \
|
||||||
|
OR lower(coalesce(e.description, '')) LIKE {like} ESCAPE '\\')"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
None => "true".into(),
|
None => "true".into(),
|
||||||
};
|
};
|
||||||
@@ -3614,6 +3619,9 @@ mod tests {
|
|||||||
assert_eq!(db.count_in(7, Some("f"), Filter::Downloaded, None).await.unwrap(), 1);
|
assert_eq!(db.count_in(7, Some("f"), Filter::Downloaded, None).await.unwrap(), 1);
|
||||||
assert_eq!(db.count_in(7, Some("f"), Filter::Flagged, None).await.unwrap(), 1);
|
assert_eq!(db.count_in(7, Some("f"), Filter::Flagged, None).await.unwrap(), 1);
|
||||||
assert_eq!(db.count_in(7, Some("f"), Filter::All, Some("dive")).await.unwrap(), 2);
|
assert_eq!(db.count_in(7, Some("f"), Filter::All, Some("dive")).await.unwrap(), 2);
|
||||||
|
for wild in ["%", "_", "\\"] {
|
||||||
|
assert_eq!(db.count_in(7, Some("f"), Filter::All, Some(wild)).await.unwrap(), 0, "{wild} is only itself");
|
||||||
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
db.count_in(7, Some("f"), Filter::All, Some("NOTES two")).await.unwrap(),
|
db.count_in(7, Some("f"), Filter::All, Some("NOTES two")).await.unwrap(),
|
||||||
1,
|
1,
|
||||||
|
|||||||
Reference in New Issue
Block a user