diff --git a/src/modes/diff.rs b/src/modes/diff.rs index e2f1943..cfb3ed7 100644 --- a/src/modes/diff.rs +++ b/src/modes/diff.rs @@ -77,6 +77,7 @@ fn setup_diff_paths_and_compression( fn setup_diff_pipes() -> Result<((libc::c_int, libc::c_int), (libc::c_int, libc::c_int)), anyhow::Error> { use nix::unistd::pipe; use nix::Error as NixError; + use std::os::fd::IntoRawFd; // Create pipes for diff's input let (fd_a_read, fd_a_write) = pipe() @@ -84,7 +85,7 @@ fn setup_diff_pipes() -> Result<((libc::c_int, libc::c_int), (libc::c_int, libc: let (fd_b_read, fd_b_write) = pipe() .map_err(|e: NixError| anyhow::anyhow!("Failed to create pipe B: {}", e))?; - Ok(((fd_a_read, fd_a_write), (fd_b_read, fd_b_write))) + Ok(((fd_a_read.into_raw_fd(), fd_a_write.into_raw_fd()), (fd_b_read.into_raw_fd(), fd_b_write.into_raw_fd()))) } diff --git a/src/modes/server/api/item.rs b/src/modes/server/api/item.rs index 8ec35ef..d7da66f 100644 --- a/src/modes/server/api/item.rs +++ b/src/modes/server/api/item.rs @@ -169,7 +169,7 @@ pub async fn handle_post_item( (status = 500, description = "Internal server error") ), params( - ("item_id" = String, Path, description = "ID of the item to delete") + ("item_id" = i64, Path, description = "ID of the item to delete") ), security( ("bearerAuth" = []) @@ -292,7 +292,7 @@ pub async fn handle_get_item_latest( (status = 500, description = "Internal server error") ), params( - ("item_id" = String, Path, description = "ID of the item to retrieve") + ("item_id" = i64, Path, description = "ID of the item to retrieve") ), security( ("bearerAuth" = []) @@ -300,7 +300,7 @@ pub async fn handle_get_item_latest( )] pub async fn handle_get_item( State(state): State, - Path(item_id): Path, + Path(item_id): Path, headers: HeaderMap, ConnectInfo(addr): ConnectInfo, ) -> Result>, StatusCode> { @@ -309,43 +309,39 @@ pub async fn handle_get_item( return Err(StatusCode::UNAUTHORIZED); } - if let Ok(id) = item_id.parse::() { - // Validate that item ID is positive to prevent path traversal issues - if id <= 0 { - warn!("Invalid item ID {} from {}", id, addr); - return Err(StatusCode::BAD_REQUEST); - } - - let mut conn = state.db.lock().await; - - if let Some(item) = db::get_item(&mut *conn, id).map_err(|e| { - warn!("Failed to get item {} for content: {}", id, e); - StatusCode::INTERNAL_SERVER_ERROR - })? { - match get_item_content(&item, &state.data_dir).await { - Ok(content) => { - let response = ApiResponse { - success: true, - data: Some(content), - error: None, - }; - Ok(Json(response)) - } - Err(e) => { - warn!("Failed to get content for item {}: {}", id, e); - let response = ApiResponse:: { - success: false, - data: None, - error: Some(format!("Failed to retrieve content: {}", e)), - }; - Ok(Json(response)) - } + // Validate that item ID is positive to prevent path traversal issues + if item_id <= 0 { + warn!("Invalid item ID {} from {}", item_id, addr); + return Err(StatusCode::BAD_REQUEST); + } + + let mut conn = state.db.lock().await; + + if let Some(item) = db::get_item(&mut *conn, item_id).map_err(|e| { + warn!("Failed to get item {} for content: {}", item_id, e); + StatusCode::INTERNAL_SERVER_ERROR + })? { + match get_item_content(&item, &state.data_dir).await { + Ok(content) => { + let response = ApiResponse { + success: true, + data: Some(content), + error: None, + }; + Ok(Json(response)) + } + Err(e) => { + warn!("Failed to get content for item {}: {}", item_id, e); + let response = ApiResponse:: { + success: false, + data: None, + error: Some(format!("Failed to retrieve content: {}", e)), + }; + Ok(Json(response)) } - } else { - Err(StatusCode::NOT_FOUND) } } else { - Err(StatusCode::BAD_REQUEST) + Err(StatusCode::NOT_FOUND) } } @@ -422,7 +418,7 @@ pub async fn handle_get_item_latest_content( (status = 500, description = "Internal server error") ), params( - ("item_id" = String, Path, description = "ID of the item to retrieve") + ("item_id" = i64, Path, description = "ID of the item to retrieve") ), security( ("bearerAuth" = []) @@ -430,7 +426,7 @@ pub async fn handle_get_item_latest_content( )] pub async fn handle_get_item_content( State(state): State, - Path(item_id): Path, + Path(item_id): Path, headers: HeaderMap, ConnectInfo(addr): ConnectInfo, ) -> Result { @@ -439,38 +435,34 @@ pub async fn handle_get_item_content( return Err(StatusCode::UNAUTHORIZED); } - if let Ok(id) = item_id.parse::() { - // Validate that item ID is positive to prevent path traversal issues - if id <= 0 { - warn!("Invalid item ID {} from {}", id, addr); - return Err(StatusCode::BAD_REQUEST); - } - - let mut conn = state.db.lock().await; - - if let Some(item) = db::get_item(&mut *conn, id).map_err(|e| { - warn!("Failed to get item {} for content: {}", id, e); - StatusCode::INTERNAL_SERVER_ERROR - })? { - match get_item_raw_content(&item, &state.data_dir, &mut *conn).await { - Ok((content, mime_type)) => { - let mut response = content.into_response(); - response.headers_mut().insert( - header::CONTENT_TYPE, - mime_type.parse().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? - ); - Ok(response) - } - Err(e) => { - warn!("Failed to get raw content for item {}: {}", id, e); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } + // Validate that item ID is positive to prevent path traversal issues + if item_id <= 0 { + warn!("Invalid item ID {} from {}", item_id, addr); + return Err(StatusCode::BAD_REQUEST); + } + + let mut conn = state.db.lock().await; + + if let Some(item) = db::get_item(&mut *conn, item_id).map_err(|e| { + warn!("Failed to get item {} for content: {}", item_id, e); + StatusCode::INTERNAL_SERVER_ERROR + })? { + match get_item_raw_content(&item, &state.data_dir, &mut *conn).await { + Ok((content, mime_type)) => { + let mut response = content.into_response(); + response.headers_mut().insert( + header::CONTENT_TYPE, + mime_type.parse().map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + ); + Ok(response) + } + Err(e) => { + warn!("Failed to get raw content for item {}: {}", item_id, e); + Err(StatusCode::INTERNAL_SERVER_ERROR) } - } else { - Err(StatusCode::NOT_FOUND) } } else { - Err(StatusCode::BAD_REQUEST) + Err(StatusCode::NOT_FOUND) } } @@ -603,7 +595,7 @@ pub async fn handle_get_item_latest_meta( (status = 500, description = "Internal server error") ), params( - ("item_id" = String, Path, description = "ID of the item to retrieve metadata for") + ("item_id" = i64, Path, description = "ID of the item to retrieve metadata for") ), security( ("bearerAuth" = []) @@ -611,7 +603,7 @@ pub async fn handle_get_item_latest_meta( )] pub async fn handle_get_item_meta( State(state): State, - Path(item_id): Path, + Path(item_id): Path, headers: HeaderMap, ConnectInfo(addr): ConnectInfo, ) -> Result>>, StatusCode> { @@ -620,34 +612,30 @@ pub async fn handle_get_item_meta( return Err(StatusCode::UNAUTHORIZED); } - if let Ok(id) = item_id.parse::() { - let mut conn = state.db.lock().await; + let mut conn = state.db.lock().await; + + if let Some(item) = db::get_item(&mut *conn, item_id).map_err(|e| { + warn!("Failed to get item {} for meta: {}", item_id, e); + StatusCode::INTERNAL_SERVER_ERROR + })? { + let item_meta = db::get_item_meta(&mut *conn, &item) + .map_err(|e| { + warn!("Failed to get metadata for item {}: {}", item_id, e); + StatusCode::INTERNAL_SERVER_ERROR + })? + .into_iter() + .map(|m| (m.name, m.value)) + .collect(); - if let Some(item) = db::get_item(&mut *conn, id).map_err(|e| { - warn!("Failed to get item {} for meta: {}", id, e); - StatusCode::INTERNAL_SERVER_ERROR - })? { - let item_meta = db::get_item_meta(&mut *conn, &item) - .map_err(|e| { - warn!("Failed to get metadata for item {}: {}", id, e); - StatusCode::INTERNAL_SERVER_ERROR - })? - .into_iter() - .map(|m| (m.name, m.value)) - .collect(); - - let response = ApiResponse { - success: true, - data: Some(item_meta), - error: None, - }; - - Ok(Json(response)) - } else { - Err(StatusCode::NOT_FOUND) - } + let response = ApiResponse { + success: true, + data: Some(item_meta), + error: None, + }; + + Ok(Json(response)) } else { - Err(StatusCode::BAD_REQUEST) + Err(StatusCode::NOT_FOUND) } }