use librqbit Id20 impl to validate info-hash bytes, require valid type for public methods

This commit is contained in:
yggverse 2025-08-08 04:10:43 +03:00
parent d61af4b970
commit 704a2e5c29
4 changed files with 24 additions and 55 deletions

View file

@ -1,4 +1,5 @@
use anyhow::{Result, bail};
use librqbit::dht::Id20;
use regex::Regex;
use std::{collections::HashSet, fs, path::PathBuf};
@ -36,14 +37,14 @@ impl Preload {
/// cleanup tmp data on success (see rqbit#408)
pub fn commit(
&self,
info_hash: &str,
info_hash: &Id20,
torrent_bytes: Vec<u8>,
persist_files: Option<HashSet<PathBuf>>,
) -> Result<()> {
validate_info_hash(info_hash)?;
let i = info_hash.as_string();
// persist preload files
let mut d = PathBuf::from(&self.root);
d.push(info_hash);
d.push(&i);
if d.exists() {
// clean previous data
fs::remove_dir_all(&d)?;
@ -87,7 +88,7 @@ impl Preload {
log::debug!("clean tmp data `{}`", tmp.to_string_lossy())
}
// persist torrent bytes to file (on previous operations success)
let t = self.torrent(info_hash);
let t = self.torrent(i);
fs::write(&t, torrent_bytes)?;
log::debug!("persist torrent bytes for `{}`", t.to_string_lossy());
Ok(())
@ -97,10 +98,9 @@ impl Preload {
/// Get absolute path to the temporary directory
/// * optionally creates directory if not exists
pub fn tmp(&self, info_hash: &str, is_create: bool) -> Result<PathBuf> {
validate_info_hash(info_hash)?;
pub fn tmp(&self, info_hash: &Id20, is_create: bool) -> Result<PathBuf> {
let mut p = PathBuf::from(&self.root);
p.push(tmp_component(info_hash));
p.push(tmp_component(info_hash.as_string()));
if p.is_file() {
bail!("Output directory `{}` is file", p.to_string_lossy())
}
@ -117,30 +117,19 @@ impl Preload {
}
/// Check the given hash is contain resolved torrent file
pub fn contains_torrent(&self, info_hash: &str) -> Result<bool> {
validate_info_hash(info_hash)?;
Ok(fs::exists(self.torrent(info_hash))?)
pub fn contains_torrent(&self, info_hash: &Id20) -> Result<bool> {
Ok(fs::exists(self.torrent(info_hash.as_string()))?)
}
/// Get absolute path to the torrent file
fn torrent(&self, info_hash: &str) -> PathBuf {
fn torrent(&self, info_hash: String) -> PathBuf {
let mut p = PathBuf::from(&self.root);
p.push(format!("{info_hash}.torrent"));
p
}
}
/// Non-expensive method to make sure the given string is safe to use in path builders
/// @TODO implement custom type?
fn validate_info_hash(value: &str) -> Result<()> {
if value.len() == 40 && value.chars().all(|c| c.is_ascii_hexdigit()) {
Ok(())
} else {
bail!("Invalid info-hash value `{value}`")
}
}
/// Build constant path component
fn tmp_component(info_hash: &str) -> String {
fn tmp_component(info_hash: String) -> String {
format!(".{info_hash}")
}