Skip to content

Commit

Permalink
[net_util, app_util, txt_util] Handle possible JSON indexing panics
Browse files Browse the repository at this point in the history
  • Loading branch information
m4heshd committed Apr 18, 2024
1 parent 42da300 commit 73a2075
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 26 deletions.
6 changes: 3 additions & 3 deletions backend/src/app_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use serde_json::json;

use crate::{
net_util::{get_latest_app_meta, JSON},
net_util::{get_latest_app_meta, JSON, JsonTryGet},
rt_util::QuitUnwrap,
};

Expand Down Expand Up @@ -71,8 +71,8 @@ pub fn get_app_root_dir() -> PathBuf {
pub async fn check_app_update() -> anyhow::Result<JSON> {
let err_msg = "Invalid version information in the app update-check response";
let remote_meta = get_latest_app_meta().await?;
let version =
Version::parse(remote_meta["version"].as_str().context(err_msg)?).context(err_msg)?;
let version = Version::parse(remote_meta.try_get("version").as_str().context(err_msg)?)
.context(err_msg)?;

if version > Version::parse(get_app_metadata().version)? {
Ok(json!({
Expand Down
56 changes: 40 additions & 16 deletions backend/src/net_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,23 @@ pub async fn download_media_tools(
tools: Vec<String>,
on_progress: impl Fn(&str, f64),
) -> anyhow::Result<()> {
let media_tools_meta = get_media_tools_meta().await?[&get_os_id()].take();
let media_tools_meta = get_media_tools_meta()
.await?
.get_mut(&get_os_id())
.context("Media tools metadata not available for the current platform")?
.take();

for tool in tools {
if is_debug() {
println!("Downloading media tool - {tool}..\n");
}

let url = media_tools_meta[&tool]["download"]
let url = media_tools_meta
.get(&tool)
.context(format!(
"No metadata available for the third-party tool - {tool}"
))?
.try_get("download")
.as_str()
.context("Invalid media-tool download URL")?;

Expand Down Expand Up @@ -286,8 +295,8 @@ pub async fn login_to_fight_pass(
let json_body: JSON = resp.json().await.context(err_msg)?;

if let (Some(auth), Some(refresh)) = (
json_body["authorisationToken"].as_str(),
json_body["refreshToken"].as_str(),
json_body.try_get("authorisationToken").as_str(),
json_body.try_get("refreshToken").as_str(),
) {
Ok(LoginSession {
user: email.to_string(),
Expand Down Expand Up @@ -344,8 +353,9 @@ pub async fn refresh_access_token() -> anyhow::Result<()> {
let json_body: JSON = resp
.json()
.await
.context("Search result contains invalid response data")?;
let auth_token = json_body["authorisationToken"].as_str();
.context("Login session refresh response contains invalid data")?;

let auth_token = json_body.try_get("authorisationToken").as_str();

match auth_token {
Some(new_auth_token) => {
Expand Down Expand Up @@ -410,7 +420,8 @@ pub async fn search_vods(query: &str, page: u64) -> anyhow::Result<JSON> {
.json()
.await
.context("Search result contains an invalid response")?;
let result = &json_body["results"][0];

let result = json_body.try_get("results").try_get(0);

if result == &JSON::Null {
Err(anyhow!("Response does not contain any search results"))
Expand Down Expand Up @@ -485,15 +496,24 @@ pub async fn get_vod_meta(url: &str) -> anyhow::Result<Vod> {
let create_vod_from_json_meta = |meta: &JSON| {
let err_msg = "VOD metadata response does not match the expected format";
let vod = Vod {
id: meta["id"].as_u64().context(err_msg)?,
title: meta["title"]
id: meta.try_get("id").as_u64().context(err_msg)?,
title: meta
.try_get("title")
.as_str()
.context(err_msg)?
.to_string()
.replace(':', " -"),
desc: meta["description"].as_str().context(err_msg)?.to_string(),
thumb: meta["thumbnailUrl"].as_str().context(err_msg)?.to_string(),
access: meta["accessLevel"].as_str().context(err_msg)? != "DENIED",
desc: meta
.try_get("description")
.as_str()
.context(err_msg)?
.to_string(),
thumb: meta
.try_get("thumbnailUrl")
.as_str()
.context(err_msg)?
.to_string(),
access: meta.try_get("accessLevel").as_str().context(err_msg)? != "DENIED",
vod_url: url.to_string(),
..Vod::default()
};
Expand Down Expand Up @@ -546,7 +566,7 @@ pub async fn get_vod_stream_url(vod_id: u64) -> anyhow::Result<String> {
.await
.context("Callback response contains invalid information")?;

if let Some(url) = json_body["playerUrlCallback"].as_str() {
if let Some(url) = json_body.try_get("playerUrlCallback").as_str() {
let resp = client
.get(url)
.send()
Expand All @@ -564,7 +584,7 @@ pub async fn get_vod_stream_url(vod_id: u64) -> anyhow::Result<String> {
.await
.context("Stream response contains invalid information")?;

if let Some(url) = json_body["hls"][0]["url"].as_str() {
if let Some(url) = json_body.try_get("hls").try_get(0).try_get("url").as_str() {
Ok(url.to_string())
} else {
Err(anyhow!("No stream URL present in the response"))
Expand All @@ -589,8 +609,12 @@ fn generate_fight_pass_api_headers() -> anyhow::Result<HeaderMap> {

/// Deserializes and returns the `messages` array from a response.
async fn get_messages_from_response(resp: Response) -> anyhow::Result<Vec<String>> {
let resp_messages =
serde_json::from_value::<Vec<String>>(resp.json::<JSON>().await?["messages"].take())?;
let resp_messages = serde_json::from_value::<Vec<String>>(
resp.json::<JSON>()
.await?
.try_get_mut("messages", &mut JSON::Null)
.take(),
)?;

Ok(resp_messages)
}
14 changes: 7 additions & 7 deletions backend/src/txt_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use reqwest::Url;
use serde_json::json;
use uuid::Uuid;

use crate::net_util::JSON;
use crate::net_util::{JSON, JsonTryGet};

/// Creates a UUID and returns it as a `String`.
pub fn create_uuid() -> String {
Expand Down Expand Up @@ -33,10 +33,10 @@ pub fn get_vod_id_from_url(url: &str) -> anyhow::Result<String> {
/// Processes stdout lines from a `yt-dlp` process and returns the progress status as JSON.
pub fn process_yt_dlp_stdout(line: &str) -> JSON {
if let Ok(dl_stat_json) = serde_json::from_str::<JSON>(line) {
let size = dl_stat_json["size"].as_str().unwrap_or("").trim();
let speed = dl_stat_json["speed"].as_str().unwrap_or("").trim();
let eta = dl_stat_json["eta"].as_str().unwrap_or("").trim();
let task = if let Some(vcodec) = dl_stat_json["vcodec"].as_str() {
let size = dl_stat_json.try_get("size").as_str().unwrap_or("").trim();
let speed = dl_stat_json.try_get("speed").as_str().unwrap_or("").trim();
let eta = dl_stat_json.try_get("eta").as_str().unwrap_or("").trim();
let task = if let Some(vcodec) = dl_stat_json.try_get("vcodec").as_str() {
if vcodec == "none" {
"audio"
} else {
Expand All @@ -47,8 +47,8 @@ pub fn process_yt_dlp_stdout(line: &str) -> JSON {
};

let progress: f64 = if let (Some(total_size), Some(dl_size)) = (
dl_stat_json["total_size"].as_f64(),
dl_stat_json["dl_size"].as_f64(),
dl_stat_json.try_get("total_size").as_f64(),
dl_stat_json.try_get("dl_size").as_f64(),
) {
((dl_size / total_size) * 100.0).round()
} else {
Expand Down

0 comments on commit 73a2075

Please sign in to comment.