Skip to content

Commit

Permalink
Merge pull request #271 from ikatson/infohash-only-url
Browse files Browse the repository at this point in the history
[feature] support 40-byte infohash (not a magnet) as a way to add torrents
  • Loading branch information
ikatson authored Nov 7, 2024
2 parents 8d2aa93 + 95f5a32 commit 835acbc
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
10 changes: 9 additions & 1 deletion crates/librqbit/src/http_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use futures::{FutureExt, TryStreamExt};
use http::{HeaderMap, HeaderValue, StatusCode};
use itertools::Itertools;

use librqbit_core::magnet::Magnet;
use serde::{Deserialize, Serialize};
use std::io::SeekFrom;
use std::net::SocketAddr;
Expand Down Expand Up @@ -118,6 +119,12 @@ impl HttpApi {
let is_url = params.is_url;
let opts = params.into_add_torrent_options();
let data = data.to_vec();
let maybe_magnet = |data: &[u8]| -> bool {
std::str::from_utf8(data)
.ok()
.and_then(|s| Magnet::parse(s).ok())
.is_some()
};
let add = match is_url {
Some(true) => AddTorrent::Url(
String::from_utf8(data)
Expand All @@ -129,7 +136,8 @@ impl HttpApi {
// Guess the format.
None if SUPPORTED_SCHEMES
.iter()
.any(|s| data.starts_with(s.as_bytes())) =>
.any(|s| data.starts_with(s.as_bytes()))
|| maybe_magnet(&data) =>
{
AddTorrent::Url(
String::from_utf8(data)
Expand Down
5 changes: 4 additions & 1 deletion crates/librqbit/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ impl<'a> AddTorrent<'a> {
if SUPPORTED_SCHEMES.iter().any(|s| path.starts_with(s)) {
return Ok(Self::Url(Cow::Borrowed(path)));
}
if path.len() == 40 && !Path::new(path).exists() && Magnet::parse(path).is_ok() {
return Ok(Self::Url(Cow::Borrowed(path)));
}
Self::from_local_filename(path)
}

Expand Down Expand Up @@ -884,7 +887,7 @@ impl Session {
// So we must discover at least one peer and connect to it to be able to proceed further.

let add_res = match add {
AddTorrent::Url(magnet) if magnet.starts_with("magnet:") => {
AddTorrent::Url(magnet) if magnet.starts_with("magnet:") || magnet.len() == 40 => {
let magnet = Magnet::parse(&magnet)
.context("provided path is not a valid magnet URL")?;
let info_hash = magnet
Expand Down
10 changes: 10 additions & 0 deletions crates/librqbit_core/src/magnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ impl Magnet {

/// Parse a magnet link.
pub fn parse(url: &str) -> anyhow::Result<Magnet> {
if url.len() == 40 {
if let Ok(id20) = Id20::from_str(url) {
return Ok(Magnet {
id20: Some(id20),
id32: None,
trackers: vec![],
select_only: None,
});
}
}
let url = url::Url::parse(url).context("magnet link must be a valid URL")?;
if url.scheme() != "magnet" {
anyhow::bail!("expected scheme magnet");
Expand Down

0 comments on commit 835acbc

Please sign in to comment.