use std::fs;
use std::fs::DirBuilder;
use json::{array, JsonValue, object};
pub struct Body {}
impl Body {
pub fn def(header: JsonValue, body: Vec<u8>) -> JsonValue {
let content_type = header["content-type"].as_str().unwrap();
let content_length = header["content-length"].to_string().parse::<usize>().unwrap();
let mut body_list = object! {
get: object! {},
post: object! {},
files: object! {},
};
body_list["get"] = Body::query(header["uri"].clone().to_string());
match content_type {
"multipart/form-data" => {
body_list = Body::multipart(header.clone(), body.clone(), body_list.clone());
}
"application/x-www-form-urlencoded" => {
if content_length == 0 {
return body_list;
}
let text: String = body.iter().map(|&c| c as char).collect();
let text: Vec<&str> = text.split("&").collect();
for item in text.iter() {
let row: Vec<&str> = item.split("=").collect();
body_list["post"][row[0].clone()] = row[1].clone().into();
}
}
"application/json" => {
if content_length == 0 {
return body_list;
}
let text: String = body.iter().map(|&c| c as char).collect();
match json::parse(&*text.clone()) {
Ok(e) => {
body_list["post"] = e.clone();
}
Err(_) => {
let str = unsafe { String::from_utf8_unchecked(body) };
match json::parse(&*str.clone()) {
Ok(e) => {
body_list["post"] = e;
}
Err(_) => {
body_list["post"] = object! {}
}
}
}
}
}
_ => {
}
}
body_list
}
pub fn multipart(header: JsonValue, data: Vec<u8>, mut body_list: JsonValue) -> JsonValue {
let boundary = header["boundary"].as_str().unwrap();
let text = unsafe { String::from_utf8_unchecked(data.clone()) };
let text = text.trim_start_matches("\r\n");
let text = text.trim_end_matches(format!("\r\n--{}--\r\n", boundary.clone()).as_str()).to_string();
let fg = format!("--{}\r\n", boundary.clone());
let list: Vec<&str> = text.split(fg.as_str().clone()).collect();
let mut index = 0;
let mut body = data[2 + fg.len()..].to_vec();
while index < list.len() {
let item = list[index].to_string();
let item = item.trim_start_matches(boundary.clone());
let len = item.len();
if len == 0 {
index += 1;
continue;
}
match item.contains("filename=") {
false => {
let row: Vec<&str> = item.split("\r\n\r\n").collect();
let field: Vec<&str> = row[0].split("\"").collect();
let name = field[1];
let row: Vec<&str> = row[1].split("\r\n").collect();
let value: Vec<&str> = row[0].split("\"").collect();
body_list["post"][name] = value[0].clone().into();
}
true => {
let text: Vec<&str> = item.split("\r\n\r\n").collect();
let body = text[1];
let file = body.trim_start_matches("\u{0}");
let file = file.trim_end_matches("\r\n");
let text: Vec<&str> = text[0].split("\r\n").collect();
let name: Vec<&str> = text[0].split("\"").collect();
let types: Vec<&str> = text[1].split(": ").collect();
let types = types[1];
let field = name[1];
let filename = name[3];
fn _content_type_mode(data: &str) -> String {
match data {
"image/png" => "png",
"image/jpeg" => "jpeg",
"image/jpg" => "jpg",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" => "xlsx",
"image/x-icon" => "ico",
_ => "txt"
}.to_string().clone()
}
let mut file_data = object! {};
file_data["type"] = types.into();
file_data["name"] = filename.into();
file_data["size"] = file.len().into();
file_data["sha"] = df_crypto::sha::str_to_sha256(file).into();
file_data["mode"] = JsonValue::String(_content_type_mode(types.clone()).clone());
let temp_file = format!("{}.{}", file_data["sha"], file_data["mode"]);
let public = header["public"].as_str().unwrap();
let temp = format!("{}/../temp", public.clone());
let filename = format!("{}/../temp/{}", public.clone(), temp_file);
file_data["temp"] = filename.clone().into();
match DirBuilder::new().recursive(true).create(temp.clone()) {
Ok(_) => true,
Err(_) => false
};
match fs::write(file_data["temp"].as_str().unwrap().clone(), file.clone()) {
Ok(_) => {
if body_list["files"][field].is_empty() {
body_list["files"][field] = array![file_data.clone()];
} else {
body_list["files"][field].push(file_data.clone()).unwrap();
}
true
}
Err(_) => {
false
}
};
}
}
index += 1;
if index == list.len() {} else {
body = body[len + fg.len()..].to_vec();
}
}
body_list
}
pub fn query(data: String) -> JsonValue {
let mut list = object! {};
let query: Vec<&str> = data.split("?").collect();
if query.len() == 1 {
return list;
}
let query = query[1].clone();
if query.is_empty() {
return list;
}
let query: Vec<&str> = query.split("&").collect();
for item in query.iter() {
let row: Vec<&str> = item.split("=").collect();
let key = row[0].clone();
let value = row[1].clone();
list[key] = value.into();
}
list
}
}