Skip to content

Commit 7803d5a

Browse files
committed
feat!: [#217] lowercase infohashes
1 parent 9133910 commit 7803d5a

File tree

7 files changed

+21
-13
lines changed

7 files changed

+21
-13
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
UPDATE torrust_torrents SET info_hash = LOWER(info_hash);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
UPDATE torrust_torrents SET info_hash = LOWER(info_hash);

src/databases/mysql.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ impl Database for Mysql {
444444
let torrent_id = query("INSERT INTO torrust_torrents (uploader_id, category_id, info_hash, size, name, pieces, piece_length, private, root_hash, date_uploaded) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, UTC_TIMESTAMP())")
445445
.bind(uploader_id)
446446
.bind(category_id)
447-
.bind(info_hash.to_uppercase())
447+
.bind(info_hash.to_lowercase())
448448
.bind(torrent.file_size())
449449
.bind(torrent.info.name.to_string())
450450
.bind(pieces)
@@ -582,7 +582,7 @@ impl Database for Mysql {
582582
query_as::<_, DbTorrentInfo>(
583583
"SELECT torrent_id, info_hash, name, pieces, piece_length, private, root_hash FROM torrust_torrents WHERE info_hash = ?",
584584
)
585-
.bind(info_hash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
585+
.bind(info_hash.to_hex_string().to_lowercase())
586586
.fetch_one(&self.pool)
587587
.await
588588
.map_err(|_| database::Error::TorrentNotFound)
@@ -652,7 +652,7 @@ impl Database for Mysql {
652652
WHERE tt.info_hash = ?
653653
GROUP BY torrent_id"
654654
)
655-
.bind(info_hash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
655+
.bind(info_hash.to_hex_string().to_lowercase())
656656
.fetch_one(&self.pool)
657657
.await
658658
.map_err(|_| database::Error::TorrentNotFound)

src/databases/sqlite.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ impl Database for Sqlite {
434434
let torrent_id = query("INSERT INTO torrust_torrents (uploader_id, category_id, info_hash, size, name, pieces, piece_length, private, root_hash, date_uploaded) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, strftime('%Y-%m-%d %H:%M:%S',DATETIME('now', 'utc')))")
435435
.bind(uploader_id)
436436
.bind(category_id)
437-
.bind(info_hash.to_uppercase())
437+
.bind(info_hash.to_lowercase())
438438
.bind(torrent.file_size())
439439
.bind(torrent.info.name.to_string())
440440
.bind(pieces)
@@ -572,7 +572,7 @@ impl Database for Sqlite {
572572
query_as::<_, DbTorrentInfo>(
573573
"SELECT torrent_id, info_hash, name, pieces, piece_length, private, root_hash FROM torrust_torrents WHERE info_hash = ?",
574574
)
575-
.bind(info_hash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
575+
.bind(info_hash.to_hex_string().to_lowercase())
576576
.fetch_one(&self.pool)
577577
.await
578578
.map_err(|_| database::Error::TorrentNotFound)
@@ -642,7 +642,7 @@ impl Database for Sqlite {
642642
WHERE tt.info_hash = ?
643643
GROUP BY ts.torrent_id"
644644
)
645-
.bind(info_hash.to_string().to_uppercase()) // `info_hash` is stored as uppercase
645+
.bind(info_hash.to_string().to_lowercase())
646646
.fetch_one(&self.pool)
647647
.await
648648
.map_err(|_| database::Error::TorrentNotFound)

src/models/torrent_file.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ impl Torrent {
193193

194194
#[must_use]
195195
pub fn info_hash(&self) -> String {
196-
from_bytes(&self.calculate_info_hash_as_bytes())
196+
from_bytes(&self.calculate_info_hash_as_bytes()).to_lowercase()
197197
}
198198

199199
#[must_use]

src/web/api/v1/contexts/torrent/handlers.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ pub async fn upload_torrent_handler(
5757
#[derive(Deserialize)]
5858
pub struct InfoHashParam(pub String);
5959

60+
impl InfoHashParam {
61+
fn lowercase(&self) -> String {
62+
self.0.to_lowercase()
63+
}
64+
}
65+
6066
/// Returns the torrent as a byte stream `application/x-bittorrent`.
6167
///
6268
/// # Errors
@@ -68,7 +74,7 @@ pub async fn download_torrent_handler(
6874
Extract(maybe_bearer_token): Extract,
6975
Path(info_hash): Path<InfoHashParam>,
7076
) -> Response {
71-
let Ok(info_hash) = InfoHash::from_str(&info_hash.0) else { return ServiceError::BadRequest.into_response() };
77+
let Ok(info_hash) = InfoHash::from_str(&info_hash.lowercase()) else { return ServiceError::BadRequest.into_response() };
7278

7379
let opt_user_id = match get_optional_logged_in_user(maybe_bearer_token, app_data.clone()).await {
7480
Ok(opt_user_id) => opt_user_id,
@@ -114,7 +120,7 @@ pub async fn get_torrent_info_handler(
114120
Extract(maybe_bearer_token): Extract,
115121
Path(info_hash): Path<InfoHashParam>,
116122
) -> Response {
117-
let Ok(info_hash) = InfoHash::from_str(&info_hash.0) else { return ServiceError::BadRequest.into_response() };
123+
let Ok(info_hash) = InfoHash::from_str(&info_hash.lowercase()) else { return ServiceError::BadRequest.into_response() };
118124

119125
let opt_user_id = match get_optional_logged_in_user(maybe_bearer_token, app_data.clone()).await {
120126
Ok(opt_user_id) => opt_user_id,
@@ -143,7 +149,7 @@ pub async fn update_torrent_info_handler(
143149
Path(info_hash): Path<InfoHashParam>,
144150
extract::Json(update_torrent_info_form): extract::Json<UpdateTorrentInfoForm>,
145151
) -> Response {
146-
let Ok(info_hash) = InfoHash::from_str(&info_hash.0) else { return ServiceError::BadRequest.into_response() };
152+
let Ok(info_hash) = InfoHash::from_str(&info_hash.lowercase()) else { return ServiceError::BadRequest.into_response() };
147153

148154
let user_id = match app_data.auth.get_user_id_from_bearer_token(&maybe_bearer_token).await {
149155
Ok(user_id) => user_id,
@@ -182,7 +188,7 @@ pub async fn delete_torrent_handler(
182188
Extract(maybe_bearer_token): Extract,
183189
Path(info_hash): Path<InfoHashParam>,
184190
) -> Response {
185-
let Ok(info_hash) = InfoHash::from_str(&info_hash.0) else { return ServiceError::BadRequest.into_response() };
191+
let Ok(info_hash) = InfoHash::from_str(&info_hash.lowercase()) else { return ServiceError::BadRequest.into_response() };
186192

187193
let user_id = match app_data.auth.get_user_id_from_bearer_token(&maybe_bearer_token).await {
188194
Ok(user_id) => user_id,

tests/e2e/web/api/v1/contexts/torrent/contract.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ mod for_guests {
176176
let expected_torrent = TorrentDetails {
177177
torrent_id: uploaded_torrent.torrent_id,
178178
uploader: uploader.username,
179-
info_hash: test_torrent.file_info.info_hash.to_uppercase(),
179+
info_hash: test_torrent.file_info.info_hash.to_lowercase(),
180180
title: test_torrent.index_info.title.clone(),
181181
description: test_torrent.index_info.description,
182182
category: Category {
@@ -203,7 +203,7 @@ mod for_guests {
203203
magnet_link: format!(
204204
// cspell:disable-next-line
205205
"magnet:?xt=urn:btih:{}&dn={}&tr={}&tr={}",
206-
test_torrent.file_info.info_hash.to_uppercase(),
206+
test_torrent.file_info.info_hash.to_lowercase(),
207207
urlencoding::encode(&test_torrent.index_info.title),
208208
encoded_tracker_url,
209209
encoded_tracker_url

0 commit comments

Comments
 (0)