mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-24 17:56:28 +00:00
fix(torrents): preserve metadata retention on malformed records
This commit is contained in:
+49
-16
@@ -7003,6 +7003,22 @@ fn db_get_all_downloads(
|
|||||||
crate::db::load_downloads(&connection)
|
crate::db::load_downloads(&connection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn retained_torrent_id_from_persisted_record(record: &str) -> Option<String> {
|
||||||
|
let value = serde_json::from_str::<serde_json::Value>(record).ok()?;
|
||||||
|
let object = value.as_object()?;
|
||||||
|
if object.get("isTorrent").and_then(serde_json::Value::as_bool) != Some(true)
|
||||||
|
|| object.get("torrentPath").is_none_or(serde_json::Value::is_null)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
object
|
||||||
|
.get("id")
|
||||||
|
.and_then(serde_json::Value::as_str)
|
||||||
|
.map(str::trim)
|
||||||
|
.filter(|id| !id.is_empty())
|
||||||
|
.map(ToOwned::to_owned)
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn db_replace_downloads(
|
fn db_replace_downloads(
|
||||||
state: tauri::State<'_, crate::db::DbState>,
|
state: tauri::State<'_, crate::db::DbState>,
|
||||||
@@ -7446,6 +7462,7 @@ mod tests {
|
|||||||
parse_media_playlist_metadata,
|
parse_media_playlist_metadata,
|
||||||
normalize_media_connections,
|
normalize_media_connections,
|
||||||
validate_enqueue_url, validate_enqueue_uris, validate_keychain_grant_request_id,
|
validate_enqueue_url, validate_enqueue_uris, validate_keychain_grant_request_id,
|
||||||
|
retained_torrent_id_from_persisted_record,
|
||||||
};
|
};
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use super::should_apply_dock_badge_update;
|
use super::should_apply_dock_badge_update;
|
||||||
@@ -7479,6 +7496,27 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn retained_torrent_metadata_survives_unrelated_persisted_field_corruption() {
|
||||||
|
let record = json!({
|
||||||
|
"id": "retained-torrent",
|
||||||
|
"isTorrent": true,
|
||||||
|
"torrentPath": "/tmp/retained-torrent.torrent",
|
||||||
|
"torrentMaxPeers": "corrupted"
|
||||||
|
})
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
retained_torrent_id_from_persisted_record(&record).as_deref(),
|
||||||
|
Some("retained-torrent")
|
||||||
|
);
|
||||||
|
assert!(retained_torrent_id_from_persisted_record("not-json").is_none());
|
||||||
|
assert!(retained_torrent_id_from_persisted_record(
|
||||||
|
&json!({ "id": "ordinary", "isTorrent": false }).to_string()
|
||||||
|
)
|
||||||
|
.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn aria2_active_connection_count_uses_only_nonnegative_daemon_values() {
|
fn aria2_active_connection_count_uses_only_nonnegative_daemon_values() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -9921,25 +9959,20 @@ pub fn run() {
|
|||||||
let retained_torrent_ids = database
|
let retained_torrent_ids = database
|
||||||
.lock()
|
.lock()
|
||||||
.and_then(|connection| crate::db::load_downloads(&connection))
|
.and_then(|connection| crate::db::load_downloads(&connection))
|
||||||
.and_then(|records| {
|
.map(|records| {
|
||||||
records
|
records
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|record| {
|
.filter_map(|record| {
|
||||||
serde_json::from_str::<crate::ipc::DownloadItem>(&record)
|
let retained = retained_torrent_id_from_persisted_record(&record);
|
||||||
.map_err(|error| {
|
if retained.is_none() {
|
||||||
format!("could not decode persisted download metadata: {error}")
|
if serde_json::from_str::<crate::ipc::DownloadItem>(&record).is_err() {
|
||||||
})
|
log::warn!(
|
||||||
|
"skipping malformed persisted download during torrent metadata retention"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retained
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()
|
|
||||||
})
|
|
||||||
.map(|downloads| {
|
|
||||||
downloads
|
|
||||||
.into_iter()
|
|
||||||
.filter(|download| {
|
|
||||||
download.is_torrent.unwrap_or(false)
|
|
||||||
&& download.torrent_path.is_some()
|
|
||||||
})
|
|
||||||
.map(|download| download.id)
|
|
||||||
.collect::<HashSet<_>>()
|
.collect::<HashSet<_>>()
|
||||||
});
|
});
|
||||||
match retained_torrent_ids {
|
match retained_torrent_ids {
|
||||||
|
|||||||
@@ -3928,6 +3928,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn torrent_options_reject_invalid_peer_values() {
|
fn torrent_options_reject_invalid_peer_values() {
|
||||||
|
assert!(normalize_torrent_max_peers(Some(-1)).is_err());
|
||||||
|
|
||||||
let mut options = serde_json::Map::new();
|
let mut options = serde_json::Map::new();
|
||||||
let payload = SpawnPayload {
|
let payload = SpawnPayload {
|
||||||
is_torrent: true,
|
is_torrent: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user