From d83f888da7010506ab8cea9ceb5310ada8777db6 Mon Sep 17 00:00:00 2001 From: William Batista Date: Wed, 17 Feb 2021 10:15:02 -0500 Subject: [PATCH] Library now panics! on invalid magnet url Another helpful redditor warned me about the dangers of not validating that the URL given is a magnet url. Unfortuanetly, I can't just change everything to use Options and Errors, so I'm making the fix of having the library just panic instead, since that would make it still backwards compatible. This will be changed in version 2.0.0 --- README.md | 52 ++++++++++++++++++++++++++++------------------------ src/lib.rs | 21 ++++++++++++++++++++- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 3fe66a2..9b38b9c 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,28 @@ [![Build Status](https://www.travis-ci.com/billyb2/parse-magnet-rs.svg?branch=main)](https://www.travis-ci.com/billyb2/parse-magnet-rs) -# The Rust Magnet URL Parser! # What is a magnet url -A magnet is a URI scheme that identifies files by their hash, - normally used in peer to peer file sharing networks (like - Bittorrent). Basically, a magnet link identifies a torrent you - want to download, and tells the torrent client how to download - it. They make it very easy to share files over the internet, - and use a combination of DHT and trackers to tell your torrent - client where other peers who can share the file with you are. +A magnet is a URI scheme that identifies files by their hash, +normally used in peer to peer file sharing networks (like +Bittorrent). Basically, a magnet link identifies a torrent you +want to download, and tells the torrent client how to download +it. They make it very easy to share files over the internet, +and use a combination of DHT and trackers to tell your torrent +client where other peers who can share the file with you are. # Why is magnet_url -While working on a side project, I realized that I had the - misfortune of trying to get the component parts of a magnet-url - and then do further processing of them. I quickly wrote some - Regex for it, but then I realized that this would be really - useful for other projects that are dealing with torrents in - Rust. By making it modifiable, too, it would allow for the - creation of custom magnet links, which would also be useful for - torrent based projects. +While working on a side project, I realized that I had the +misfortune of trying to get the component parts of a magnet-url +and then do further processing of them. I quickly wrote some +Regex for it, but then I realized that this would be really +useful for other projects that are dealing with torrents in +Rust. By making it modifiable, too, it would allow for the +creation of custom magnet links, which would also be useful for +torrent based projects. # Why use magnet_url - magnet_url has the goal of, as you may have guessed, parsing the parts of magnets. It does - this using some relatively simple regexes. The crate is designed to be very simple and efficient, - with a lot of flexibility. It's also designed to be relatively easy to handle errors, and - modification of it's source is greatly encouraged through documentation and it's license. +magnet_url has the goal of, as you may have guessed, parsing the parts of magnets. It does +this using some relatively simple regexes. The crate is designed to be very simple and efficient, +with a lot of flexibility. It's also designed to be relatively easy to handle errors, and +modification of it's source is greatly encouraged through documentation and it's license. ## How to use this crate Parsing a magnet is very simple: @@ -57,7 +56,6 @@ parameters! ``` use magnet_url::Magnet; - let magneturl = //Note, this magnet won't actually download, sorry :/ Magnet { dn: "hello_world".to_string(), @@ -67,13 +65,19 @@ parameters! tr: { let mut tr_vec = Vec::new(); - tr_vec.push("https://example.com/".to_string()) + tr_vec.push("https://example.com/".to_string()); tr_vec }, kt: "cool+stuff".to_string(), ws: String::new(), acceptable_source: String::new(), mt: String::new(), - + xs: String::new(), }; -``` + ``` + +Invalid magnet url's will result in a panic! (This will be changed to an error in v2.0.0 + ```#[should_panic] + use magnet_url::Magnet; + let _magnet_link = Magnet::new("https://example.com"); + ``` \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index b14caf7..c91e570 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ use regex::Regex; extern crate lazy_static; ///The regexes used to identify specific parts of the magnet +const MAGNET_URL_RE_STR: &str = r"^(stratum-|)magnet:\?"; const DISPLAY_NAME_RE_STR: &str = r"dn=([A-Za-z0-9!@#$%^:*<>,?/()_+=.{}\{}\-]*)(&|$|\s)"; const EXACT_TOPIC_RE_STR: &str = r"xt=urn:(sha1|btih|ed2k|aich|kzhash|md5|tree:tiger):([A-Fa-f0-9]+|[A-Za-z2-7]+)"; const ADDRESS_TRACKER_RE_STR: &str = r"tr=([A-Za-z0-9!@#$%^:*<>,?/()_+=.{}\{}\-]*)(&|$|\s)"; @@ -71,7 +72,6 @@ const MANIFEST_TOPIC_RE_STR: &str = r"mt=((\w+)[A-Za-z0-9!@#$%^:*<>,?/()_+=.{}\\ /// /// ``` /// use magnet_url::Magnet; -/// let magneturl = /// //Note, this magnet won't actually download, sorry :/ /// Magnet { /// dn: "hello_world".to_string(), @@ -91,6 +91,12 @@ const MANIFEST_TOPIC_RE_STR: &str = r"mt=((\w+)[A-Za-z0-9!@#$%^:*<>,?/()_+=.{}\\ /// xs: String::new(), /// }; /// ``` +/// +/// Invalid magnet url's will result in a panic! (This will be changed to an error in v2.0.0 +/// ```#[should_panic] +/// use magnet_url::Magnet; +/// let _magnet_link = Magnet::new("https://example.com"); +/// ``` pub struct Magnet { ///Display Name of the torrent pub dn: String, @@ -134,6 +140,7 @@ impl Magnet { */ pub fn new (magnet_str: &str) -> Magnet { lazy_static! { + static ref MAGNET_URL_RE: Regex = Regex::new(MAGNET_URL_RE_STR).unwrap(); static ref DISPLAY_NAME_RE: Regex = Regex::new(DISPLAY_NAME_RE_STR).unwrap(); static ref EXACT_TOPIC_RE: Regex = Regex::new(EXACT_TOPIC_RE_STR).unwrap(); static ref EXACT_LENGTH_RE: Regex = Regex::new(EXACT_LENGTH_RE_STR).unwrap(); @@ -145,6 +152,11 @@ impl Magnet { static ref MANIFEST_TOPIC_RE: Regex = Regex::new(MANIFEST_TOPIC_RE_STR).unwrap(); } + // Panicking is a temporary fix, in version 2.0.0 it will instead return an Error + if MAGNET_URL_RE.is_match(magnet_str) == false { + panic!("Invalid magnet url") + } + let validate_regex = |regex: &Regex, re_group_index| -> String { match regex.captures(magnet_str) { Some(m) => m.get(re_group_index).map_or("", |m| m.as_str()).to_string(), @@ -206,4 +218,11 @@ mod tests { assert_eq!(magnet_link.acceptable_source, String::new()); assert_eq!(magnet_link.mt, String::new()); } + + #[test] + #[should_panic] + fn invalid_magnet_test() { + let _magnet_link = Magnet::new("https://example.com"); + + } }