mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-22 21:39:21 +00:00
Add support for multiple files types
This commit is contained in:
parent
dc93d58d6b
commit
afcce8463f
84
Cargo.lock
generated
84
Cargo.lock
generated
@ -500,7 +500,7 @@ version = "0.1.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244"
|
checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint 0.2.6",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
@ -640,6 +640,27 @@ dependencies = [
|
|||||||
"bytes 1.0.1",
|
"bytes 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b"
|
||||||
|
dependencies = [
|
||||||
|
"bzip2-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2-sys"
|
||||||
|
version = "0.1.10+1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17fa3d1ac1ca21c5c4e36a97f3c3eb25084576f6fc47bf0139c1123434216c6c"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.66"
|
version = "1.0.66"
|
||||||
@ -707,6 +728,8 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"mailchecker",
|
"mailchecker",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
|
"mp3-metadata",
|
||||||
|
"mp4",
|
||||||
"mysql",
|
"mysql",
|
||||||
"pdf",
|
"pdf",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
@ -718,6 +741,7 @@ dependencies = [
|
|||||||
"sha1",
|
"sha1",
|
||||||
"webrtc-sdp",
|
"webrtc-sdp",
|
||||||
"yaml-rust",
|
"yaml-rust",
|
||||||
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -957,15 +981,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.20"
|
version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0"
|
checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 0.1.10",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"libc",
|
"libc",
|
||||||
"libz-sys",
|
"libz-sys",
|
||||||
"miniz_oxide 0.4.3",
|
"miniz_oxide 0.3.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1527,6 +1551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
|
checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
|
"libc",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
@ -1727,6 +1752,26 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mp3-metadata"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb969bc3573726b0bf60238d5d70f1aa6cc0f9e87f8db3e047b8309317319699"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mp4"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "999db0cca8fd8c1b2352f362691bdafbd90069efd581144066a7909895d23b86"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"bytes 0.5.6",
|
||||||
|
"num-rational",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mutate_once"
|
name = "mutate_once"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -1771,7 +1816,7 @@ dependencies = [
|
|||||||
"flate2",
|
"flate2",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lexical",
|
"lexical",
|
||||||
"num-bigint",
|
"num-bigint 0.2.6",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"regex",
|
"regex",
|
||||||
@ -1855,6 +1900,17 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.44"
|
version = "0.1.44"
|
||||||
@ -1883,8 +1939,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"num-bigint 0.3.1",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3249,3 +3307,17 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"linked-hash-map",
|
"linked-hash-map",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "0.5.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a8977234acab718eb2820494b2f96cbb16004c19dddf88b7445b27381450997"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"bzip2",
|
||||||
|
"crc32fast",
|
||||||
|
"flate2",
|
||||||
|
"thiserror",
|
||||||
|
"time 0.1.44",
|
||||||
|
]
|
||||||
|
@ -34,3 +34,6 @@ dashmap = "4.0.2"
|
|||||||
reqwest = { version = "0.11.1", features = ["json", "blocking"] }
|
reqwest = { version = "0.11.1", features = ["json", "blocking"] }
|
||||||
webrtc-sdp = "0.3.8"
|
webrtc-sdp = "0.3.8"
|
||||||
bcrypt = "0.9.0"
|
bcrypt = "0.9.0"
|
||||||
|
mp3-metadata = "0.3.3"
|
||||||
|
mp4 = "0.8.1"
|
||||||
|
zip = "0.5.10"
|
@ -39,7 +39,7 @@ database:
|
|||||||
password: pierre
|
password: pierre
|
||||||
|
|
||||||
# If set to true, every requests made on the database will be shown on the terminal
|
# If set to true, every requests made on the database will be shown on the terminal
|
||||||
log-all-queries: true
|
log-all-queries: false
|
||||||
|
|
||||||
|
|
||||||
# Video calls configuration
|
# Video calls configuration
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::constants::{conservation_policy, MIN_SUPPORTED_MOBILE_VERSION, password_policy, MIN_CONVERSATION_MESSAGE_LENGTH, MAX_CONVERSATION_MESSAGE_LENGTH};
|
use crate::constants::{ALLOWED_CONVERSATION_FILES_TYPES, conservation_policy, CONVERSATION_FILES_MAX_SIZE, MAX_CONVERSATION_MESSAGE_LENGTH, MIN_CONVERSATION_MESSAGE_LENGTH, MIN_SUPPORTED_MOBILE_VERSION, password_policy};
|
||||||
use crate::data::config::conf;
|
use crate::data::config::conf;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@ -39,6 +39,8 @@ pub struct ServerConfig {
|
|||||||
data_conservation_policy: DataConservationPolicy,
|
data_conservation_policy: DataConservationPolicy,
|
||||||
min_conversation_message_len: usize,
|
min_conversation_message_len: usize,
|
||||||
max_conversation_message_len: usize,
|
max_conversation_message_len: usize,
|
||||||
|
allowed_conversation_files_type: [&'static str; 17],
|
||||||
|
conversation_files_max_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerConfig {
|
impl ServerConfig {
|
||||||
@ -52,6 +54,8 @@ impl ServerConfig {
|
|||||||
|
|
||||||
min_conversation_message_len: MIN_CONVERSATION_MESSAGE_LENGTH,
|
min_conversation_message_len: MIN_CONVERSATION_MESSAGE_LENGTH,
|
||||||
max_conversation_message_len: MAX_CONVERSATION_MESSAGE_LENGTH,
|
max_conversation_message_len: MAX_CONVERSATION_MESSAGE_LENGTH,
|
||||||
|
allowed_conversation_files_type: ALLOWED_CONVERSATION_FILES_TYPES,
|
||||||
|
conversation_files_max_size: CONVERSATION_FILES_MAX_SIZE,
|
||||||
|
|
||||||
password_policy: PasswordPolicy {
|
password_policy: PasswordPolicy {
|
||||||
allow_email_in_password: password_policy::ALLOW_EMAIL_IN_PASSWORD,
|
allow_email_in_password: password_policy::ALLOW_EMAIL_IN_PASSWORD,
|
||||||
|
@ -167,3 +167,28 @@ pub const MIN_SUPPORTED_MOBILE_VERSION: &str = "1.1.1";
|
|||||||
/// Minimum message length
|
/// Minimum message length
|
||||||
pub const MIN_CONVERSATION_MESSAGE_LENGTH: usize = 1;
|
pub const MIN_CONVERSATION_MESSAGE_LENGTH: usize = 1;
|
||||||
pub const MAX_CONVERSATION_MESSAGE_LENGTH: usize = 16000;
|
pub const MAX_CONVERSATION_MESSAGE_LENGTH: usize = 16000;
|
||||||
|
|
||||||
|
/// Allowed files type in conversations
|
||||||
|
pub const ALLOWED_CONVERSATION_FILES_TYPES: [&str; 17] = [
|
||||||
|
"image/png", "image/jpeg", "image/gif", "image/bmp",
|
||||||
|
"application/pdf",
|
||||||
|
"audio/mpeg",
|
||||||
|
"video/mp4",
|
||||||
|
"application/zip",
|
||||||
|
|
||||||
|
// MS Office docs
|
||||||
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||||
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
|
||||||
|
// Open Office docs
|
||||||
|
"application/vnd.oasis.opendocument.text",
|
||||||
|
"application/vnd.oasis.opendocument.presentation",
|
||||||
|
"application/vnd.oasis.opendocument.spreadsheet",
|
||||||
|
|
||||||
|
// Source code docs (UTF-8 encoded)
|
||||||
|
"text/x-csrc", "text/plain", "text/x-c++src"
|
||||||
|
];
|
||||||
|
|
||||||
|
/// File maximum size in conversations (10 Mb)
|
||||||
|
pub const CONVERSATION_FILES_MAX_SIZE: usize = 10 * 1024 * 1024;
|
@ -2,16 +2,15 @@
|
|||||||
//!
|
//!
|
||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
|
||||||
use crate::api_data::conversation_api::ConversationAPI;
|
use crate::api_data::conversation_api::ConversationAPI;
|
||||||
use crate::api_data::conversation_message_api::ConversationMessageAPI;
|
use crate::api_data::conversation_message_api::ConversationMessageAPI;
|
||||||
use crate::api_data::list_unread_conversations_api::UnreadConversationAPI;
|
use crate::api_data::list_unread_conversations_api::UnreadConversationAPI;
|
||||||
use crate::api_data::res_count_unread_conversations::ResultCountUnreadConversations;
|
use crate::api_data::res_count_unread_conversations::ResultCountUnreadConversations;
|
||||||
use crate::api_data::res_create_conversation::ResCreateConversation;
|
use crate::api_data::res_create_conversation::ResCreateConversation;
|
||||||
use crate::api_data::res_find_private_conversations::ResFindPrivateConversations;
|
use crate::api_data::res_find_private_conversations::ResFindPrivateConversations;
|
||||||
use crate::constants::{MAX_CONVERSATION_MESSAGE_LENGTH, MIN_CONVERSATION_MESSAGE_LENGTH};
|
use crate::constants::{ALLOWED_CONVERSATION_FILES_TYPES, CONVERSATION_FILES_MAX_SIZE, MAX_CONVERSATION_MESSAGE_LENGTH, MIN_CONVERSATION_MESSAGE_LENGTH};
|
||||||
use crate::controllers::user_ws_controller;
|
use crate::controllers::user_ws_controller;
|
||||||
use crate::data::base_request_handler::BaseRequestHandler;
|
use crate::data::base_request_handler::{BaseRequestHandler, RequestValue};
|
||||||
use crate::data::conversation::{ConversationMemberSetting, NewConversationSettings};
|
use crate::data::conversation::{ConversationMemberSetting, NewConversationSettings};
|
||||||
use crate::data::conversation_message::ConversationMessageFile;
|
use crate::data::conversation_message::ConversationMessageFile;
|
||||||
use crate::data::error::Res;
|
use crate::data::error::Res;
|
||||||
@ -25,6 +24,7 @@ use crate::helpers::{conversations_helper, events_helper, user_helper};
|
|||||||
use crate::helpers::events_helper::Event;
|
use crate::helpers::events_helper::Event;
|
||||||
use crate::routes::RequestResult;
|
use crate::routes::RequestResult;
|
||||||
use crate::utils::string_utils::remove_html_nodes;
|
use crate::utils::string_utils::remove_html_nodes;
|
||||||
|
use crate::utils::user_data_utils::{delete_user_data_file_if_exists, user_data_path};
|
||||||
|
|
||||||
/// Create a new conversation
|
/// Create a new conversation
|
||||||
pub fn create(r: &mut HttpRequestHandler) -> RequestResult {
|
pub fn create(r: &mut HttpRequestHandler) -> RequestResult {
|
||||||
@ -251,22 +251,100 @@ pub fn send_message(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
// TODO : add support for other files type
|
// TODO : add support for other files type
|
||||||
|
|
||||||
// Get image
|
// Get associated file
|
||||||
let file = match r.has_file("image") {
|
let file = match r.post_parameter_opt("file") {
|
||||||
false => None,
|
Some(RequestValue::File(file)) => {
|
||||||
true => {
|
|
||||||
let path = r.save_post_image("image", "conversations", 1200, 1200)?;
|
// File name
|
||||||
Some(ConversationMessageFile {
|
let mut name = file.name.to_string();
|
||||||
path: path.clone(),
|
|
||||||
size: std::fs::metadata(&path)?.len(),
|
if file.buff.len() > CONVERSATION_FILES_MAX_SIZE {
|
||||||
name: "picture.png".to_string(),
|
r.bad_request("File is too big!".to_string())?;
|
||||||
thumbnail: Some(r.save_post_image("image", "conversations", 50, 50)?),
|
|
||||||
r#type: "image/png".to_string(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine file mime type
|
||||||
|
let mut mime_type = r.post_file_type("file")?;
|
||||||
|
|
||||||
|
// Check for thumbnail
|
||||||
|
let mut thumbnail = match r.has_file("thumbnail") {
|
||||||
|
false => None,
|
||||||
|
true => Some("thumbnail".to_string())
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get message, if there is no image
|
let path;
|
||||||
|
|
||||||
|
if !ALLOWED_CONVERSATION_FILES_TYPES.contains(&mime_type.as_str()) {
|
||||||
|
r.bad_request("File type is not allowed!".to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Images
|
||||||
|
if mime_type.starts_with("image/") {
|
||||||
|
if let None = thumbnail {
|
||||||
|
thumbnail = Some("file".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
path = r.save_post_image("file", "conversation", 2000, 2000)?;
|
||||||
|
mime_type = "image/png".to_string();
|
||||||
|
name = "picture.png".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PDF
|
||||||
|
else if mime_type.eq("application/pdf") {
|
||||||
|
path = r.save_post_pdf("file", "conversation")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MP3
|
||||||
|
else if mime_type.eq("audio/mpeg") {
|
||||||
|
path = r.save_post_mp3("file", "conversation")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MP4
|
||||||
|
else if mime_type.eq("video/mp4") {
|
||||||
|
path = r.save_post_mp4("file", "conversation")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZIP archive
|
||||||
|
else if mime_type.eq("application/zip") {
|
||||||
|
path = r.save_post_zip("file", "conversation")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Office document
|
||||||
|
else if mime_type.starts_with("application/") {
|
||||||
|
path = r.save_post_office_doc("file", "conversation")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text files
|
||||||
|
else {
|
||||||
|
path = r.save_post_txt_doc("file", "conversation")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Attempt to save thumbnail, if it fails we can not save message
|
||||||
|
let thumbnail = match thumbnail {
|
||||||
|
None => None,
|
||||||
|
Some(f) => Some(match r.save_post_image(&f, "conversations-thumb", 200, 200) {
|
||||||
|
Ok(s) => Ok(s),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to save conversation thumbnail! {:#?}", e);
|
||||||
|
delete_user_data_file_if_exists(&path).unwrap();
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}?)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Some(ConversationMessageFile {
|
||||||
|
path: path.clone(),
|
||||||
|
size: std::fs::metadata(user_data_path(path.as_ref()))?.len(),
|
||||||
|
name,
|
||||||
|
thumbnail,
|
||||||
|
r#type: mime_type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get message, if there is no file
|
||||||
let message = if let None = file {
|
let message = if let None = file {
|
||||||
let msg = r.post_string_without_html("message", MIN_CONVERSATION_MESSAGE_LENGTH, true)?;
|
let msg = r.post_string_without_html("message", MIN_CONVERSATION_MESSAGE_LENGTH, true)?;
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
//! Base handling code for all user requests
|
//! Base handling code for all user requests
|
||||||
|
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use exif::In;
|
use exif::In;
|
||||||
@ -23,11 +24,14 @@ use crate::data::user_token::UserAccessToken;
|
|||||||
use crate::helpers::{account_helper, comments_helper, conversations_helper, custom_emojies_helper, friends_helper, groups_helper, posts_helper, user_helper, virtual_directory_helper};
|
use crate::helpers::{account_helper, comments_helper, conversations_helper, custom_emojies_helper, friends_helper, groups_helper, posts_helper, user_helper, virtual_directory_helper};
|
||||||
use crate::helpers::virtual_directory_helper::VirtualDirType;
|
use crate::helpers::virtual_directory_helper::VirtualDirType;
|
||||||
use crate::routes::RequestResult;
|
use crate::routes::RequestResult;
|
||||||
|
use crate::utils::mp3_utils::is_valid_mp3;
|
||||||
|
use crate::utils::mp4_utils::is_valid_mp4;
|
||||||
use crate::utils::pdf_utils::is_valid_pdf;
|
use crate::utils::pdf_utils::is_valid_pdf;
|
||||||
use crate::utils::string_utils::{check_emoji_code, check_string_before_insert, check_url, remove_html_nodes, check_html_color};
|
use crate::utils::string_utils::{check_emoji_code, check_html_color, check_string_before_insert, check_url, remove_html_nodes};
|
||||||
use crate::utils::user_data_utils::{generate_new_user_data_file_name, prepare_file_creation, user_data_path};
|
use crate::utils::user_data_utils::{generate_new_user_data_file_name, prepare_file_creation, user_data_path};
|
||||||
use crate::utils::virtual_directories_utils;
|
use crate::utils::virtual_directories_utils;
|
||||||
use std::collections::HashSet;
|
use crate::utils::zip_utils::is_valid_zip;
|
||||||
|
use std::str::from_utf8;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct SuccessMessage {
|
struct SuccessMessage {
|
||||||
@ -272,6 +276,34 @@ pub trait BaseRequestHandler {
|
|||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the mime type of a file included in the request
|
||||||
|
fn post_file_type(&mut self, name: &str) -> Res<String> {
|
||||||
|
let file = self.post_file(name)?;
|
||||||
|
|
||||||
|
let filetype = mime_guess::from_path(&file.name)
|
||||||
|
.first()
|
||||||
|
.map(|m| format!("{}/{}", m.type_(), m.subtype()));
|
||||||
|
|
||||||
|
if let None = filetype {
|
||||||
|
self.bad_request(format!("Could not determine file type in '{}' !", name))?;
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(filetype.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the extension of a file included in the request
|
||||||
|
fn post_file_ext(&mut self, name: &str, default: &str) -> Res<String> {
|
||||||
|
let suffix = self.post_file_type(name)?
|
||||||
|
.parse::<mime_guess::mime::Mime>()?
|
||||||
|
.suffix()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(default)
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
Ok(suffix)
|
||||||
|
}
|
||||||
|
|
||||||
/// Save an image in user data directory
|
/// Save an image in user data directory
|
||||||
fn save_post_image(&mut self, name: &str, folder: &str, max_w: u32, max_h: u32) -> ResultBoxError<String> {
|
fn save_post_image(&mut self, name: &str, folder: &str, max_w: u32, max_h: u32) -> ResultBoxError<String> {
|
||||||
|
|
||||||
@ -329,8 +361,25 @@ pub trait BaseRequestHandler {
|
|||||||
Ok(target_file_path.to_string_lossy().to_string())
|
Ok(target_file_path.to_string_lossy().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Save a file included in the request
|
||||||
|
fn save_post_file(&mut self, name: &str, folder: &str, ext: &str) -> Res<String> {
|
||||||
|
let file = self.post_file(name)?;
|
||||||
|
|
||||||
|
// Avoid memory warnings
|
||||||
|
let copied_buff = file.buff.clone();
|
||||||
|
|
||||||
|
// Determine pdf file destination
|
||||||
|
let target_user_data_folder = prepare_file_creation(self.user_id_ref()?, folder)?;
|
||||||
|
let target_file_path = generate_new_user_data_file_name(target_user_data_folder.as_path(), ext)?;
|
||||||
|
let target_sys_path = user_data_path(target_file_path.as_path());
|
||||||
|
|
||||||
|
std::fs::write(target_sys_path, &copied_buff.as_ref())?;
|
||||||
|
|
||||||
|
Ok(target_file_path.to_string_lossy().to_string())
|
||||||
|
}
|
||||||
|
|
||||||
/// Save a pdf included in the request
|
/// Save a pdf included in the request
|
||||||
fn save_post_pdf(&mut self, name: &str, folder: &str) -> ResultBoxError<String> {
|
fn save_post_pdf(&mut self, name: &str, folder: &str) -> Res<String> {
|
||||||
let file = self.post_file(name)?;
|
let file = self.post_file(name)?;
|
||||||
|
|
||||||
if !is_valid_pdf(&file.buff)? {
|
if !is_valid_pdf(&file.buff)? {
|
||||||
@ -338,17 +387,76 @@ pub trait BaseRequestHandler {
|
|||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid memory warnings
|
self.save_post_file(name, folder, "pdf")
|
||||||
let copied_buff = file.buff.clone();
|
}
|
||||||
|
|
||||||
// Determine pdf file destination
|
/// Save a mp3 file included in the request
|
||||||
let target_user_data_folder = prepare_file_creation(self.user_id_ref()?, folder)?;
|
fn save_post_mp3(&mut self, name: &str, folder: &str) -> Res<String> {
|
||||||
let target_file_path = generate_new_user_data_file_name(target_user_data_folder.as_path(), "pdf")?;
|
let file = self.post_file(name)?;
|
||||||
let target_sys_path = user_data_path(target_file_path.as_path());
|
|
||||||
|
|
||||||
std::fs::write(target_sys_path, &copied_buff.as_ref())?;
|
if !is_valid_mp3(&file.buff) {
|
||||||
|
self.bad_request(format!("Invalid MP3 file specified in {} !", name))?;
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(target_file_path.to_string_lossy().to_string())
|
self.save_post_file(name, folder, "mp3")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save a mp4 file included in the request
|
||||||
|
fn save_post_mp4(&mut self, name: &str, folder: &str) -> Res<String> {
|
||||||
|
let file = self.post_file(name)?;
|
||||||
|
|
||||||
|
if !is_valid_mp4(&file.buff) {
|
||||||
|
self.bad_request(format!("Invalid MP4 file specified in {} !", name))?;
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.save_post_file(name, folder, "mp4")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save a zip file included in the request
|
||||||
|
fn save_post_zip(&mut self, name: &str, folder: &str) -> Res<String> {
|
||||||
|
let file = self.post_file(name)?;
|
||||||
|
|
||||||
|
if !is_valid_zip(&file.buff) {
|
||||||
|
self.bad_request(format!("Invalid ZIP archive file specified in {} !", name))?;
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.save_post_file(name, folder, "zip")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save an office document included in the request
|
||||||
|
fn save_post_office_doc(&mut self, name: &str, folder: &str) -> Res<String> {
|
||||||
|
let file = self.post_file(name)?;
|
||||||
|
|
||||||
|
if !is_valid_zip(&file.buff) {
|
||||||
|
self.bad_request(format!("Invalid ZIP archive file specified in {} !", name))?;
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mime = self.post_file_type(name)?;
|
||||||
|
|
||||||
|
if !mime.starts_with("application/") {
|
||||||
|
self.bad_request(format!("Invalid file name in {} !", name))?;
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let ext = &self.post_file_ext(name, "zip")?;
|
||||||
|
self.save_post_file(name, folder, ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save a simple text document included in the request
|
||||||
|
fn save_post_txt_doc(&mut self, name: &str, folder: &str) -> Res<String> {
|
||||||
|
let file = self.post_file(name)?;
|
||||||
|
|
||||||
|
if from_utf8(&file.buff).is_err() {
|
||||||
|
self.bad_request(format!("File in {} is not UTF-8!", name))?;
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let ext = &self.post_file_ext(name, "txt")?;
|
||||||
|
self.save_post_file(name, folder, ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an integer included in the POST request
|
/// Get an integer included in the POST request
|
||||||
|
@ -8,3 +8,6 @@ pub mod virtual_directories_utils;
|
|||||||
pub mod date_utils;
|
pub mod date_utils;
|
||||||
pub mod string_utils;
|
pub mod string_utils;
|
||||||
pub mod pdf_utils;
|
pub mod pdf_utils;
|
||||||
|
pub mod mp3_utils;
|
||||||
|
pub mod mp4_utils;
|
||||||
|
pub mod zip_utils;
|
16
src/utils/mp3_utils.rs
Normal file
16
src/utils/mp3_utils.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//! # MP3 utilities
|
||||||
|
//!
|
||||||
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
/// Check out whether a file is a valid MP3 file or not
|
||||||
|
pub fn is_valid_mp3(file: &[u8]) -> bool {
|
||||||
|
let res = mp3_metadata::read_from_slice(file);
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(_) => true,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error while parsing MP3 file ! {:#?}", e);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/utils/mp4_utils.rs
Normal file
17
src/utils/mp4_utils.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//! # MP utilities
|
||||||
|
//!
|
||||||
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
/// Check out whether an MP4 file is valid or not
|
||||||
|
pub fn is_valid_mp4(file: &[u8]) -> bool {
|
||||||
|
let cursor = std::io::Cursor::new(file);
|
||||||
|
let reader = mp4::Mp4Reader::read_header(cursor, file.len() as u64);
|
||||||
|
|
||||||
|
match reader {
|
||||||
|
Ok(_) => true,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to read MP4! {:#?}", e);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
src/utils/zip_utils.rs
Normal file
16
src/utils/zip_utils.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//! # ZIP utilities
|
||||||
|
//!
|
||||||
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
/// Check out whether a given file is a valid ZIP archive or not
|
||||||
|
pub fn is_valid_zip(file: &[u8]) -> bool {
|
||||||
|
let cursor = std::io::Cursor::new(file);
|
||||||
|
|
||||||
|
match zip::ZipArchive::new(cursor) {
|
||||||
|
Ok(_) => true,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to read ZIP archive! {:#?}", e);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user