diff --git a/src/config/parser.rs b/src/config/parser.rs index 1b8ba16..1cce7b0 100644 --- a/src/config/parser.rs +++ b/src/config/parser.rs @@ -1,7 +1,7 @@ //! This module provides the functionality to parse the lua config and convert the config options //! into rust readable form. -use crate::handler::paths::{file_path, FileType}; +use crate::handler::{file_path, FileType}; use crate::models::parser_models::{AggregatorConfig, RateLimiter, Style}; use log::LevelFilter; diff --git a/src/handler/mod.rs b/src/handler/mod.rs index 188767d..f6cf2d7 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -1,5 +1,115 @@ -//! This module provides modules which provide the functionality to handle paths for different -//! files present on different paths and provide one appropriate path on which it is present and -//! can be used. +//! This module provides the functionality to handle theme folder present on different paths and +//! provide one appropriate path on which it is present and can be used. -pub mod paths; +use std::collections::HashMap; +use std::io::Error; +use std::path::Path; +use std::sync::OnceLock; + +// ------- Constants -------- +/// The constant holding the name of the theme folder. +const PUBLIC_DIRECTORY_NAME: &str = "public"; +/// The constant holding the name of the common folder. +const COMMON_DIRECTORY_NAME: &str = "websurfx"; +/// The constant holding the name of the config file. +const CONFIG_FILE_NAME: &str = "config.lua"; +/// The constant holding the name of the AllowList text file. +const ALLOWLIST_FILE_NAME: &str = "allowlist.txt"; +/// The constant holding the name of the BlockList text file. +const BLOCKLIST_FILE_NAME: &str = "blocklist.txt"; + +/// An enum type which provides different variants to handle paths for various files/folders. +#[derive(Hash, PartialEq, Eq, Debug)] +pub enum FileType { + /// This variant handles all the paths associated with the config file. + Config, + /// This variant handles all the paths associated with the Allowlist text file. + AllowList, + /// This variant handles all the paths associated with the BlockList text file. + BlockList, + /// This variant handles all the paths associated with the public folder (Theme folder). + Theme, +} + +/// A static variable which stores the different filesystem paths for various file/folder types. +static FILE_PATHS_FOR_DIFF_FILE_TYPES: OnceLock>> = OnceLock::new(); + +/// A function which returns an appropriate path for thr provided file type by checking if the path +/// for the given file type exists on that path. +/// +/// # Error +/// +/// Returns a ` folder/file not found!!` error if the give file_type folder/file is not +/// present on the path on which it is being tested. +/// +/// # Example +/// +/// If this function is give the file_type of Theme variant then the theme folder is checked by the +/// following steps: +/// +/// 1. `/opt/websurfx` if it not present here then it fallbacks to the next one (2) +/// 2. Under project folder ( or codebase in other words) if it is not present +/// here then it returns an error as mentioned above. +pub fn file_path(file_type: FileType) -> Result<&'static str, Error> { + let home = env!("HOME"); + + let file_path: &Vec = FILE_PATHS_FOR_DIFF_FILE_TYPES + .get_or_init(|| { + HashMap::from([ + ( + FileType::Config, + vec![ + format!( + "{}/.config/{}/{}", + home, COMMON_DIRECTORY_NAME, CONFIG_FILE_NAME + ), + format!("/etc/xdg/{}/{}", COMMON_DIRECTORY_NAME, CONFIG_FILE_NAME), + format!("./{}/{}", COMMON_DIRECTORY_NAME, CONFIG_FILE_NAME), + ], + ), + ( + FileType::Theme, + vec![ + format!("/opt/websurfx/{}/", PUBLIC_DIRECTORY_NAME), + format!("./{}/", PUBLIC_DIRECTORY_NAME), + ], + ), + ( + FileType::AllowList, + vec![ + format!( + "{}/.config/{}/{}", + home, COMMON_DIRECTORY_NAME, ALLOWLIST_FILE_NAME + ), + format!("/etc/xdg/{}/{}", COMMON_DIRECTORY_NAME, ALLOWLIST_FILE_NAME), + format!("./{}/{}", COMMON_DIRECTORY_NAME, ALLOWLIST_FILE_NAME), + ], + ), + ( + FileType::BlockList, + vec![ + format!( + "{}/.config/{}/{}", + home, COMMON_DIRECTORY_NAME, BLOCKLIST_FILE_NAME + ), + format!("/etc/xdg/{}/{}", COMMON_DIRECTORY_NAME, BLOCKLIST_FILE_NAME), + format!("./{}/{}", COMMON_DIRECTORY_NAME, BLOCKLIST_FILE_NAME), + ], + ), + ]) + }) + .get(&file_type) + .unwrap(); + + for path in file_path.iter() { + if Path::new(path).exists() { + return Ok(path); + } + } + + // if no of the configs above exist, return error + Err(Error::new( + std::io::ErrorKind::NotFound, + format!("{:?} file/folder not found!!", file_type), + )) +} diff --git a/src/handler/paths.rs b/src/handler/paths.rs deleted file mode 100644 index 9ea5fff..0000000 --- a/src/handler/paths.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! This module provides the functionality to handle theme folder present on different paths and -//! provide one appropriate path on which it is present and can be used. - -use std::collections::HashMap; -use std::io::Error; -use std::path::Path; -use std::sync::OnceLock; - -// ------- Constants -------- -/// The constant holding the name of the theme folder. -const PUBLIC_DIRECTORY_NAME: &str = "public"; -/// The constant holding the name of the common folder. -const COMMON_DIRECTORY_NAME: &str = "websurfx"; -/// The constant holding the name of the config file. -const CONFIG_FILE_NAME: &str = "config.lua"; -/// The constant holding the name of the AllowList text file. -const ALLOWLIST_FILE_NAME: &str = "allowlist.txt"; -/// The constant holding the name of the BlockList text file. -const BLOCKLIST_FILE_NAME: &str = "blocklist.txt"; - -/// An enum type which provides different variants to handle paths for various files/folders. -#[derive(Hash, PartialEq, Eq, Debug)] -pub enum FileType { - /// This variant handles all the paths associated with the config file. - Config, - /// This variant handles all the paths associated with the Allowlist text file. - AllowList, - /// This variant handles all the paths associated with the BlockList text file. - BlockList, - /// This variant handles all the paths associated with the public folder (Theme folder). - Theme, -} - -/// A static variable which stores the different filesystem paths for various file/folder types. -static FILE_PATHS_FOR_DIFF_FILE_TYPES: OnceLock>> = OnceLock::new(); - -/// A function which returns an appropriate path for thr provided file type by checking if the path -/// for the given file type exists on that path. -/// -/// # Error -/// -/// Returns a ` folder/file not found!!` error if the give file_type folder/file is not -/// present on the path on which it is being tested. -/// -/// # Example -/// -/// If this function is give the file_type of Theme variant then the theme folder is checked by the -/// following steps: -/// -/// 1. `/opt/websurfx` if it not present here then it fallbacks to the next one (2) -/// 2. Under project folder ( or codebase in other words) if it is not present -/// here then it returns an error as mentioned above. -pub fn file_path(file_type: FileType) -> Result<&'static str, Error> { - let file_path: &Vec = FILE_PATHS_FOR_DIFF_FILE_TYPES - .get_or_init(|| { - HashMap::from([ - ( - FileType::Config, - vec![ - format!( - "{}/.config/{}/{}", - std::env::var("HOME").unwrap(), - COMMON_DIRECTORY_NAME, - CONFIG_FILE_NAME - ), - format!("/etc/xdg/{}/{}", COMMON_DIRECTORY_NAME, CONFIG_FILE_NAME), - format!("./{}/{}", COMMON_DIRECTORY_NAME, CONFIG_FILE_NAME), - ], - ), - ( - FileType::Theme, - vec![ - format!("/opt/websurfx/{}/", PUBLIC_DIRECTORY_NAME), - format!("./{}/", PUBLIC_DIRECTORY_NAME), - ], - ), - ( - FileType::AllowList, - vec![ - format!( - "{}/.config/{}/{}", - std::env::var("HOME").unwrap(), - COMMON_DIRECTORY_NAME, - ALLOWLIST_FILE_NAME - ), - format!("/etc/xdg/{}/{}", COMMON_DIRECTORY_NAME, ALLOWLIST_FILE_NAME), - format!("./{}/{}", COMMON_DIRECTORY_NAME, ALLOWLIST_FILE_NAME), - ], - ), - ( - FileType::BlockList, - vec![ - format!( - "{}/.config/{}/{}", - std::env::var("HOME").unwrap(), - COMMON_DIRECTORY_NAME, - BLOCKLIST_FILE_NAME - ), - format!("/etc/xdg/{}/{}", COMMON_DIRECTORY_NAME, BLOCKLIST_FILE_NAME), - format!("./{}/{}", COMMON_DIRECTORY_NAME, BLOCKLIST_FILE_NAME), - ], - ), - ]) - }) - .get(&file_type) - .unwrap(); - - for (idx, _) in file_path.iter().enumerate() { - if Path::new(file_path[idx].as_str()).exists() { - return Ok(std::mem::take(&mut &*file_path[idx])); - } - } - - // if no of the configs above exist, return error - Err(Error::new( - std::io::ErrorKind::NotFound, - format!("{:?} file/folder not found!!", file_type), - )) -} diff --git a/src/lib.rs b/src/lib.rs index 1d245fb..f64e607 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,7 @@ use actix_governor::{Governor, GovernorConfigBuilder}; use actix_web::{dev::Server, http::header, middleware::Logger, web, App, HttpServer}; use cache::cacher::{Cache, SharedCache}; use config::parser::Config; -use handler::paths::{file_path, FileType}; +use handler::{file_path, FileType}; /// Runs the web server on the provided TCP listener and returns a `Server` instance. /// diff --git a/src/results/aggregator.rs b/src/results/aggregator.rs index 5c53864..e7fc090 100644 --- a/src/results/aggregator.rs +++ b/src/results/aggregator.rs @@ -2,7 +2,7 @@ //! search engines and then removes duplicate results. use super::user_agent::random_user_agent; -use crate::handler::paths::{file_path, FileType}; +use crate::handler::{file_path, FileType}; use crate::models::{ aggregation_models::{EngineErrorInfo, SearchResult, SearchResults}, engine_models::{EngineError, EngineHandler}, diff --git a/src/server/router.rs b/src/server/router.rs index 31b7e6a..ea8387b 100644 --- a/src/server/router.rs +++ b/src/server/router.rs @@ -4,7 +4,7 @@ use crate::{ config::parser::Config, - handler::paths::{file_path, FileType}, + handler::{file_path, FileType}, }; use actix_web::{get, web, HttpRequest, HttpResponse}; use std::fs::read_to_string; diff --git a/src/server/routes/search.rs b/src/server/routes/search.rs index 35c9cc4..ae2c48d 100644 --- a/src/server/routes/search.rs +++ b/src/server/routes/search.rs @@ -3,7 +3,7 @@ use crate::{ cache::cacher::SharedCache, config::parser::Config, - handler::paths::{file_path, FileType}, + handler::{file_path, FileType}, models::{ aggregation_models::SearchResults, engine_models::{EngineError, EngineHandler}, @@ -47,54 +47,25 @@ pub async fn search( .insert_header(("location", "/")) .finish()); } - let page = match ¶ms.page { - Some(page) => *page, - None => 1, - }; - let (_, results, _) = join!( + let get_results = |page| { results( - format!( - "http://{}:{}/search?q={}&page={}&safesearch=", - config.binding_ip, - config.port, - query, - page - 1, - ), - &config, - &cache, - query, - page - 1, - req.clone(), - ¶ms.safesearch - ), - results( - format!( - "http://{}:{}/search?q={}&page={}&safesearch=", - config.binding_ip, config.port, query, page - ), &config, &cache, query, page, req.clone(), - ¶ms.safesearch - ), - results( - format!( - "http://{}:{}/search?q={}&page={}&safesearch=", - config.binding_ip, - config.port, - query, - page + 1, - ), - &config, - &cache, - query, - page + 1, - req.clone(), - ¶ms.safesearch + ¶ms.safesearch, ) + }; + + // .max(1) makes sure that the page > 0. + let page = params.page.unwrap_or(1).max(1); + + let (_, results, _) = join!( + get_results(page - 1), + get_results(page), + get_results(page + 1) ); Ok(HttpResponse::Ok().body( @@ -129,7 +100,6 @@ pub async fn search( /// It returns the `SearchResults` struct if the search results could be successfully fetched from /// the cache or from the upstream search engines otherwise it returns an appropriate error. async fn results( - url: String, config: &Config, cache: &web::Data, query: &str, @@ -137,6 +107,14 @@ async fn results( req: HttpRequest, safe_search: &Option, ) -> Result> { + let url = format!( + "http://{}:{}/search?q={}&page={}&safesearch=", + config.binding_ip, + config.port, + query, + page - 1, + ); + // fetch the cached results json. let cached_results = cache.cached_json(&url).await; // check if fetched cache results was indeed fetched or it was an error and if so @@ -157,11 +135,11 @@ async fn results( if safe_search_level == 4 { let mut results: SearchResults = SearchResults::default(); - let mut _flag: bool = - is_match_from_filter_list(file_path(FileType::BlockList)?, query)?; - _flag = !is_match_from_filter_list(file_path(FileType::AllowList)?, query)?; - if _flag { + let flag: bool = + !is_match_from_filter_list(file_path(FileType::BlockList)?, query)?; + + if flag { results.set_disallowed(); cache.cache_results(&results, &url).await?; results.set_safe_search_level(safe_search_level); @@ -264,14 +242,13 @@ fn is_match_from_filter_list( file_path: &str, query: &str, ) -> Result> { - let mut flag = false; let mut reader = BufReader::new(File::open(file_path)?); for line in reader.by_ref().lines() { let re = Regex::new(&line?)?; if re.is_match(query) { - flag = true; - break; + return Ok(true); } } - Ok(flag) + + Ok(false) } diff --git a/src/templates/partials/settings_tabs/user_interface.rs b/src/templates/partials/settings_tabs/user_interface.rs index 90e1ce9..c978c3e 100644 --- a/src/templates/partials/settings_tabs/user_interface.rs +++ b/src/templates/partials/settings_tabs/user_interface.rs @@ -1,6 +1,6 @@ //! A module that handles the user interface tab for setting page view in the `websurfx` frontend. -use crate::handler::paths::{file_path, FileType}; +use crate::handler::{file_path, FileType}; use maud::{html, Markup}; use std::fs::read_dir; diff --git a/src/templates/views/search.rs b/src/templates/views/search.rs index 440d585..9fef7f0 100644 --- a/src/templates/views/search.rs +++ b/src/templates/views/search.rs @@ -93,7 +93,7 @@ pub fn search( img src="./images/no_selection.png" alt="Image of a white cross inside a red circle"; } } - @else{ + @else { .result_not_found { p{"Your search - "{(query)}" - did not match any documents."} p class="suggestions"{"Suggestions:"}