UPNP: better ID handling + only ASCII in URLs

This commit is contained in:
Igor Katson 2024-09-02 11:41:33 +01:00
parent 65623f2074
commit 8d10a8a69c
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5
2 changed files with 30 additions and 28 deletions

View file

@ -30,6 +30,7 @@ use upnp_serve::{
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
struct TorrentFileTreeNode { struct TorrentFileTreeNode {
title: String, title: String,
// must be set for all nodes except the root node.
parent_id: Option<usize>, parent_id: Option<usize>,
children: Vec<usize>, children: Vec<usize>,
@ -62,16 +63,12 @@ impl TorrentFileTreeNode {
match self.real_torrent_file_id { match self.real_torrent_file_id {
Some(fid) => { Some(fid) => {
let filename = &torrent.shared().file_infos[fid].relative_filename; let filename = &torrent.shared().file_infos[fid].relative_filename;
// Torrent path joined with "/" let extension = filename.extension().and_then(|e| e.to_str());
let last_url_bit = torrent // Samsung TVs don't support utf-8 in URLs, so just use the ID instead of the actual title.
.shared() let last_url_bit = match extension {
.info Some(e) => format!("{encoded_id}.{e}"),
.iter_filenames_and_lengths() None => format!("{encoded_id}"),
.ok() };
.and_then(|mut it| it.nth(fid))
.and_then(|(fi, _)| fi.to_vec().ok())
.map(|components| components.join("/"))
.unwrap_or_else(|| self.title.clone());
ItemOrContainer::Item(Item { ItemOrContainer::Item(Item {
id: encoded_id, id: encoded_id,
parent_id: encoded_parent_id.unwrap_or_default(), parent_id: encoded_parent_id.unwrap_or_default(),
@ -89,7 +86,7 @@ impl TorrentFileTreeNode {
} }
None => ItemOrContainer::Container(Container { None => ItemOrContainer::Container(Container {
id: encoded_id, id: encoded_id,
parent_id: encoded_parent_id, parent_id: Some(encoded_parent_id.unwrap_or_default()),
title: self.title.clone(), title: self.title.clone(),
children_count: Some(self.children.len()), children_count: Some(self.children.len()),
}), }),
@ -124,7 +121,7 @@ impl TorrentFileTree {
.context("bug")??; .context("bug")??;
let root_node = TorrentFileTreeNode { let root_node = TorrentFileTreeNode {
title: filename.to_owned(), title: filename.to_owned(),
parent_id: Some(0), parent_id: None,
children: vec![], children: vec![],
real_torrent_file_id: Some(0), real_torrent_file_id: Some(0),
}; };
@ -213,18 +210,15 @@ impl UpnpServerSessionAdapter {
// Just add the file directly // Just add the file directly
let rf = &t.shared().file_infos[0].relative_filename; let rf = &t.shared().file_infos[0].relative_filename;
let title = rf.file_name()?.to_str()?.to_owned(); let title = rf.file_name()?.to_str()?.to_owned();
let mime_type = mime_guess::from_path(rf).first(); Some(
let url = format!( TorrentFileTreeNode {
"http://{}:{}/torrents/{real_id}/stream/0/{title}", title,
hostname, self.port parent_id: None,
); children: vec![],
Some(ItemOrContainer::Item(Item { real_torrent_file_id: Some(0),
id: upnp_id, }
parent_id: 0, .as_item_or_container(0, hostname, t, self),
title, )
mime_type,
url,
}))
} else { } else {
let title = t let title = t
.shared() .shared()
@ -572,10 +566,13 @@ mod tests {
vec![ vec![
ItemOrContainer::Item(Item { ItemOrContainer::Item(Item {
id: encode_id(0, 0), id: encode_id(0, 0),
parent_id: Some(0), parent_id: 0,
title: "f1".into(), title: "f1".into(),
mime_type: None, mime_type: None,
url: "http://127.0.0.1:9005/torrents/0/stream/0/f1".into() url: format!(
"http://127.0.0.1:9005/torrents/0/stream/0/{}",
encode_id(0, 0)
)
}), }),
ItemOrContainer::Container(Container { ItemOrContainer::Container(Container {
id: encode_id(0, 1), id: encode_id(0, 1),
@ -600,10 +597,13 @@ mod tests {
adapter.browse_direct_children(encode_id(1, 1), "127.0.0.1"), adapter.browse_direct_children(encode_id(1, 1), "127.0.0.1"),
vec![ItemOrContainer::Item(Item { vec![ItemOrContainer::Item(Item {
id: encode_id(2, 1), id: encode_id(2, 1),
parent_id: Some(encode_id(1, 1) as isize), parent_id: encode_id(1, 1),
title: "f2".into(), title: "f2".into(),
mime_type: None, mime_type: None,
url: "http://127.0.0.1:9005/torrents/1/stream/0/d1/f2".into() url: format!(
"http://127.0.0.1:9005/torrents/1/stream/0/{}",
encode_id(2, 1)
)
})] })]
); );
} }

View file

@ -62,6 +62,8 @@ pub mod browse {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Container { pub struct Container {
pub id: usize, pub id: usize,
// Parent id is None only for the root container.
// The only way to see the root container is BrowseMetadata on ObjectID=0
pub parent_id: Option<usize>, pub parent_id: Option<usize>,
pub children_count: Option<usize>, pub children_count: Option<usize>,
pub title: String, pub title: String,