Make cargo clippy happy

This commit is contained in:
Matéo Duparc 2021-08-18 16:09:52 +02:00
parent dce526922e
commit 5ae61222f4
Signed by: hardcoresushi
GPG Key ID: 007F84120107191E
8 changed files with 138 additions and 154 deletions

View File

@ -335,32 +335,35 @@ profileDiv.onclick = function() {
changePasswordButton.textContent = "Change password";
changePasswordButton.onclick = function() {
let inputs = document.querySelectorAll("input[type=\"password\"]");
let newPassword, newPasswordConfirm;
let newPassword, newPasswordConfirm, oldPassword;
if (isIdentityProtected) {
newPassword = inputs[1];
newPasswordConfirm = inputs[2];
oldPassword = inputs[0].value;
newPassword = inputs[1].value;
newPasswordConfirm = inputs[2].value;
} else {
newPassword = inputs[0];
newPasswordConfirm = inputs[1];
newPassword = inputs[0].value;
newPasswordConfirm = inputs[1].value;
}
if (newPassword.value == newPasswordConfirm.value) {
let newPassword_set = newPassword.value.length > 0;
if (isIdentityProtected || newPassword_set) { //don't change password if identity is not protected and new password is blank
if (newPassword == newPasswordConfirm) {
let newPasswordSet = newPassword.length > 0;
if (isIdentityProtected && oldPassword.length == 0) {
errorMsg.textContent = "Current password cannot be empty.";
} else if (isIdentityProtected || newPasswordSet) { //don't change password if identity is not protected and new password is blank
let msg = "change_password";
if (isIdentityProtected) {
msg += " "+b64EncodeUnicode(inputs[0].value);
}
if (newPassword_set) {
msg += " "+b64EncodeUnicode(newPassword.value);
if (newPasswordSet) {
msg += " "+b64EncodeUnicode(newPassword);
}
socket.send(msg);
} else {
removePopup();
}
} else {
newPassword.value = "";
newPasswordConfirm.value = "";
errorMsg.textContent = "Passwords don't match";
newPassword = "";
newPasswordConfirm = "";
errorMsg.textContent = "Passwords don't match.";
}
};
sectionPassword.appendChild(changePasswordButton);

View File

@ -94,8 +94,8 @@ impl Identity {
};
Ok(Contact {
uuid: contact_uuid,
public_key: public_key,
name: name,
public_key,
name,
avatar: avatar_uuid,
verified: false,
seen: true,
@ -277,8 +277,7 @@ impl Identity {
let encrypted_outgoing: Vec<u8> = row.get(0).unwrap();
match crypto::decrypt_data(encrypted_outgoing.as_slice(), &self.master_key){
Ok(outgoing) => {
match byte_to_bool(outgoing[0]) {
Ok(outgoing) => {
if let Ok(outgoing) = byte_to_bool(outgoing[0]) {
let encrypted_timestamp: Vec<u8> = row.get(1).unwrap();
match crypto::decrypt_data(&encrypted_timestamp, &self.master_key) {
Ok(timestamp) => {
@ -295,9 +294,6 @@ impl Identity {
Err(e) => print_error!(e)
}
}
Err(_) => {}
}
}
Err(e) => print_error!(e)
}
@ -382,14 +378,8 @@ impl Identity {
pub fn load_identity(password: Option<&[u8]>) -> Result<Identity, String> {
match Identity::load_encrypted_identity() {
Ok(encrypted_identity) => {
let master_key: [u8; crypto::MASTER_KEY_LEN] = if password.is_none() {
if encrypted_identity.encrypted_master_key.len() == crypto::MASTER_KEY_LEN {
encrypted_identity.encrypted_master_key.try_into().unwrap()
} else {
return Err(String::from(DATABASE_CORRUPED_ERROR))
}
} else {
match crypto::decrypt_master_key(&encrypted_identity.encrypted_master_key, password.unwrap(), &encrypted_identity.salt) {
let master_key: [u8; crypto::MASTER_KEY_LEN] = match password {
Some(password) => match crypto::decrypt_master_key(&encrypted_identity.encrypted_master_key, password, &encrypted_identity.salt) {
Ok(master_key) => master_key,
Err(e) => return Err(
match e {
@ -398,6 +388,11 @@ impl Identity {
}
)
}
None => if encrypted_identity.encrypted_master_key.len() == crypto::MASTER_KEY_LEN {
encrypted_identity.encrypted_master_key.try_into().unwrap()
} else {
return Err(String::from(DATABASE_CORRUPED_ERROR))
}
};
match crypto::decrypt_data(&encrypted_identity.encrypted_keypair, &master_key) {
Ok(keypair) => {
@ -443,13 +438,16 @@ impl Identity {
let db = KeyValueTable::new(&get_database_path(), MAIN_TABLE)?;
db.set(DBKeys::NAME, name.as_bytes())?;
db.set(DBKeys::KEYPAIR, &encrypted_keypair)?;
let salt = if password.is_none() { //no password
db.set(DBKeys::MASTER_KEY, &master_key)?; //storing master_key in plaintext
[0; crypto::SALT_LEN]
} else {
let (salt, encrypted_master_key) = crypto::encrypt_master_key(master_key, password.unwrap());
let salt = match password {
Some(password) => {
let (salt, encrypted_master_key) = crypto::encrypt_master_key(master_key, password);
db.set(DBKeys::MASTER_KEY, &encrypted_master_key)?;
salt
}
None => {
db.set(DBKeys::MASTER_KEY, &master_key)?; //storing master_key in plaintext
[0; crypto::SALT_LEN]
}
};
db.set(DBKeys::SALT, &salt)?;
let encrypted_use_padding = crypto::encrypt_data(&[bool_to_byte(true)], &master_key).unwrap();
@ -464,13 +462,16 @@ impl Identity {
fn update_master_key(master_key: [u8; crypto::MASTER_KEY_LEN], new_password: Option<&[u8]>) -> Result<usize, rusqlite::Error> {
let db = KeyValueTable::new(&get_database_path(), MAIN_TABLE)?;
let salt = if new_password.is_none() { //no password
db.update(DBKeys::MASTER_KEY, &master_key)?;
[0; crypto::SALT_LEN]
} else {
let (salt, encrypted_master_key) = crypto::encrypt_master_key(master_key, new_password.unwrap());
let salt = match new_password {
Some(new_password) => {
let (salt, encrypted_master_key) = crypto::encrypt_master_key(master_key, new_password);
db.update(DBKeys::MASTER_KEY, &encrypted_master_key)?;
salt
}
None => {
db.update(DBKeys::MASTER_KEY, &master_key)?;
[0; crypto::SALT_LEN]
}
};
db.update(DBKeys::SALT, &salt)
}
@ -478,20 +479,19 @@ impl Identity {
pub fn change_password(old_password: Option<&[u8]>, new_password: Option<&[u8]>) -> Result<bool, String> {
match Identity::load_encrypted_identity() {
Ok(encrypted_identity) => {
let master_key: [u8; crypto::MASTER_KEY_LEN] = if old_password.is_none() {
if encrypted_identity.encrypted_master_key.len() == crypto::MASTER_KEY_LEN {
encrypted_identity.encrypted_master_key.try_into().unwrap()
} else {
return Err(String::from(DATABASE_CORRUPED_ERROR))
}
} else {
match crypto::decrypt_master_key(&encrypted_identity.encrypted_master_key, old_password.unwrap(), &encrypted_identity.salt) {
let master_key: [u8; crypto::MASTER_KEY_LEN] = match old_password {
Some(old_password) => match crypto::decrypt_master_key(&encrypted_identity.encrypted_master_key, old_password, &encrypted_identity.salt) {
Ok(master_key) => master_key,
Err(e) => return match e {
CryptoError::DecryptionFailed => Ok(false),
CryptoError::InvalidLength => Err(String::from(DATABASE_CORRUPED_ERROR))
}
}
None => if encrypted_identity.encrypted_master_key.len() == crypto::MASTER_KEY_LEN {
encrypted_identity.encrypted_master_key.try_into().unwrap()
} else {
return Err(String::from(DATABASE_CORRUPED_ERROR))
}
};
match Identity::update_master_key(master_key, new_password) {
Ok(_) => Ok(true),

View File

@ -12,7 +12,7 @@ impl<'a> KeyValueTable<'a> {
Ok(KeyValueTable {db, table_name})
}
pub fn set(&self, key: &str, value: &[u8]) -> Result<usize, Error> {
Ok(self.db.execute(&format!("INSERT INTO {} (key, value) VALUES (?1, ?2)", self.table_name), params![key, value])?)
self.db.execute(&format!("INSERT INTO {} (key, value) VALUES (?1, ?2)", self.table_name), params![key, value])
}
pub fn get(&self, key: &str) -> Result<Vec<u8>, Error> {
let mut stmt = self.db.prepare(&format!("SELECT value FROM {} WHERE key=\"{}\"", self.table_name, key))?;

View File

@ -8,7 +8,7 @@ mod ui_interface;
mod constants;
mod discovery;
use std::{env, fs, io, net::SocketAddr, str::{FromStr, from_utf8}, sync::{Arc, RwLock}};
use std::{env, fs, io, net::SocketAddr, str::{FromStr, from_utf8}, sync::{Arc, RwLock}, cmp::Ordering};
use image::GenericImageView;
use tokio::{net::TcpListener, runtime::Handle, sync::mpsc};
use actix_web::{App, HttpMessage, HttpRequest, HttpResponse, HttpServer, http::{header, CookieBuilder}, web, web::Data};
@ -25,8 +25,8 @@ use session_manager::{SessionManager, SessionCommand};
use ui_interface::UiConnection;
async fn start_websocket_server(global_vars: Arc<RwLock<GlobalVars>>) -> u16 {
let websocket_bind_addr = env::var("AIRA_WEBSOCKET_ADDR").unwrap_or("127.0.0.1".to_owned());
let websocket_port = env::var("AIRA_WEBSOCKET_PORT").unwrap_or("0".to_owned());
let websocket_bind_addr = env::var("AIRA_WEBSOCKET_ADDR").unwrap_or_else(|_| "127.0.0.1".to_owned());
let websocket_port = env::var("AIRA_WEBSOCKET_PORT").unwrap_or_else(|_| "0".to_owned());
let server = TcpListener::bind(websocket_bind_addr+":"+&websocket_port).await.unwrap();
let websocket_port = server.local_addr().unwrap().port();
tokio::spawn(async move {
@ -114,7 +114,7 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc<RwLo
}
}
session_manager.get_saved_msgs().into_iter().for_each(|msgs| {
if msgs.1.len() > 0 {
if !msgs.1.is_empty() {
ui_connection.load_msgs(&msgs.0, &msgs.1);
}
});
@ -157,7 +157,7 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc<RwLo
let mut ui_connection = ui_connection.clone();
let session_manager = session_manager.clone();
handle.spawn(async move {
let args: Vec<&str> = msg.split(" ").collect();
let args: Vec<&str> = msg.split_whitespace().collect();
match args[0] {
"set_seen" => {
let session_id: usize = args[1].parse().unwrap();
@ -177,9 +177,11 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc<RwLo
let msg_content = &msg[args[0].len()+args[1].len()+2..];
let buffer = protocol::new_message(msg_content);
#[allow(unused_must_use)] {
session_manager.send_or_add_to_pending(&session_id, buffer).await.map(|sent| if !sent {
if let Ok(sent) = session_manager.send_or_add_to_pending(&session_id, buffer).await {
if !sent {
ui_connection.new_pending_msg(&session_id, false, msg_content);
});
}
}
}
}
"large_files" => {
@ -274,11 +276,11 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc<RwLo
(None, Some(base64::decode(args[1]).unwrap()))
};
let result = Identity::change_password(old_password.as_deref(), new_password.as_deref());
if old_password.is_some() {
old_password.unwrap().zeroize();
if let Some(mut old_password) = old_password {
old_password.zeroize();
}
let is_identity_protected = if new_password.is_some() {
new_password.unwrap().zeroize();
let is_identity_protected = if let Some(mut new_password) = new_password {
new_password.zeroize();
true
} else {
false
@ -337,12 +339,10 @@ async fn handle_set_avatar(req: HttpRequest, mut payload: Multipart) -> HttpResp
match image::load_from_memory_with_format(&buffer, format) {
Ok(image) => {
let (width, height) = image.dimensions();
let image = if width < height {
image.crop_imm(0, (height-width)/2, width, width)
} else if width > height {
image.crop_imm((width-height)/2, 0, height, height)
} else {
image
let image = match width.cmp(&height) {
Ordering::Greater => image.crop_imm((width-height)/2, 0, height, height),
Ordering::Less => image.crop_imm(0, (height-width)/2, width, width),
Ordering::Equal => image,
};
let mut avatar = Vec::new();
image.write_to(&mut avatar, format).unwrap();
@ -385,7 +385,7 @@ fn reply_with_avatar(avatar: Option<Vec<u8>>, name: Option<&str>) -> HttpRespons
let svg = include_str!(concat!(env!("OUT_DIR"), "/text_avatar.svg"));
#[cfg(debug_assertions)]
let svg = replace_fields("src/frontend/imgs/text_avatar.svg");
HttpResponse::Ok().content_type("image/svg+xml").body(svg.replace("LETTER", &name.chars().nth(0).unwrap_or('?').to_string()))
HttpResponse::Ok().content_type("image/svg+xml").body(svg.replace("LETTER", &name.chars().next().unwrap_or('?').to_string()))
}
None => HttpResponse::InternalServerError().finish()
}
@ -393,7 +393,7 @@ fn reply_with_avatar(avatar: Option<Vec<u8>>, name: Option<&str>) -> HttpRespons
}
fn handle_avatar(req: HttpRequest) -> HttpResponse {
let splits: Vec<&str> = req.path()[1..].split("/").collect();
let splits: Vec<&str> = req.path()[1..].split('/').collect();
if splits.len() == 2 {
if splits[1] == "self" {
return reply_with_avatar(Identity::get_identity_avatar().ok(), Identity::get_identity_name().ok().as_deref());
@ -417,12 +417,9 @@ fn handle_load_file(req: HttpRequest, file_info: web::Query<FileInfo>) -> HttpRe
match Uuid::from_str(&file_info.uuid) {
Ok(uuid) => {
let global_vars = req.app_data::<Data<Arc<RwLock<GlobalVars>>>>().unwrap();
match global_vars.read().unwrap().session_manager.identity.read().unwrap().as_ref().unwrap().load_file(uuid) {
Some(buffer) => {
if let Some(buffer) = global_vars.read().unwrap().session_manager.identity.read().unwrap().as_ref().unwrap().load_file(uuid) {
return HttpResponse::Ok().header("Content-Disposition", format!("attachment; filename=\"{}\"", escape_double_quote(html_escape::decode_html_entities(&file_info.file_name).to_string()))).content_type("application/octet-stream").body(buffer);
}
None => {}
}
}
Err(e) => print_error!(e)
}
@ -572,7 +569,7 @@ fn handle_login(req: HttpRequest, mut params: web::Form<LoginParams>) -> HttpRes
let global_vars = req.app_data::<Data<Arc<RwLock<GlobalVars>>>>().unwrap();
on_identity_loaded(identity, global_vars)
}
Err(e) => generate_login_response(Some(&e.to_string()))
Err(e) => generate_login_response(Some(&e))
};
params.password.zeroize();
response
@ -621,7 +618,7 @@ async fn handle_create(req: HttpRequest, mut params: web::Form<CreateParams>) ->
let response = if params.password == params.password_confirm {
match Identity::create_identidy(
&params.name,
if params.password.len() == 0 { //no password
if params.password.is_empty() { //no password
None
} else {
Some(params.password.as_bytes())
@ -693,7 +690,7 @@ fn replace_fields(file_path: &str) -> String {
}
fn handle_static(req: HttpRequest) -> HttpResponse {
let splits: Vec<&str> = req.path()[1..].split("/").collect();
let splits: Vec<&str> = req.path()[1..].split('/').collect();
if splits[0] == "static" {
let mut response_builder = HttpResponse::Ok();
match splits[1] {
@ -717,7 +714,7 @@ fn handle_static(req: HttpRequest) -> HttpResponse {
} else {
"none"
};
match match splits[3] {
if let Some(body) = match splits[3] {
"verified" => Some(include_str!("frontend/imgs/icons/verified.svg")),
"add_contact" => Some(include_str!("frontend/imgs/icons/add_contact.svg")),
"remove_contact" => Some(include_str!("frontend/imgs/icons/remove_contact.svg")),
@ -732,12 +729,9 @@ fn handle_static(req: HttpRequest) -> HttpResponse {
"profile" => Some(include_str!("frontend/imgs/icons/profile.svg")),
_ => None
} {
Some(body) => {
response_builder.content_type("image/svg+xml");
return response_builder.body(body.replace("FILL_COLOR", color))
}
None => {}
}
} else if splits.len() == 3 {
match splits[2] {
"wallpaper" => return response_builder.content_type("image/jpeg").body(&include_bytes!("frontend/imgs/wallpaper.jpeg")[..]),
@ -776,13 +770,12 @@ fn handle_static(req: HttpRequest) -> HttpResponse {
}
"libs" => {
if splits.len() == 3 {
match match splits[2] {
if let Some(body) = match splits[2] {
"linkify.min.js" => Some(include_str!("frontend/libs/linkify.min.js")),
"linkify-element.min.js" => Some(include_str!("frontend/libs/linkify-element.min.js")),
_ => None
} {
Some(body) => return response_builder.content_type(JS_CONTENT_TYPE).body(body),
None => {}
return response_builder.content_type(JS_CONTENT_TYPE).body(body);
}
}
}
@ -794,7 +787,7 @@ fn handle_static(req: HttpRequest) -> HttpResponse {
#[actix_web::main]
async fn start_http_server(global_vars: Arc<RwLock<GlobalVars>>) -> io::Result<()> {
let http_addr = env::var("AIRA_HTTP_ADDR").unwrap_or("127.0.0.1".to_owned()).parse().expect("AIRA_HTTP_ADDR invalid");
let http_addr = env::var("AIRA_HTTP_ADDR").unwrap_or_else(|_| "127.0.0.1".to_owned()).parse().expect("AIRA_HTTP_ADDR invalid");
let http_port = match env::var("AIRA_HTTP_PORT") {
Ok(port) => port.parse().expect("AIRA_HTTP_PORT invalid"),
Err(_) => constants::UI_PORT

View File

@ -33,7 +33,7 @@ pub fn file(file_name: &str, buffer: &[u8]) -> Vec<u8> {
[&[Headers::FILE], &(file_name.len() as u16).to_be_bytes()[..], file_name.as_bytes(), buffer].concat()
}
pub fn get_file_name<'a>(buffer: &'a [u8]) -> Option<&'a str> {
pub fn get_file_name(buffer: &[u8]) -> Option<&str> {
if buffer.len() > 3 {
let file_name_len = u16::from_be_bytes([buffer[1], buffer[2]]) as usize;
if buffer.len() > 3+file_name_len {
@ -43,7 +43,7 @@ pub fn get_file_name<'a>(buffer: &'a [u8]) -> Option<&'a str> {
None
}
pub fn parse_file<'a>(buffer: &'a [u8]) -> Option<(&'a str, &'a [u8])> {
pub fn parse_file(buffer: &[u8]) -> Option<(&str, &[u8])> {
let file_name = get_file_name(buffer)?;
Some((file_name, &buffer[3+file_name.len()..]))
}

View File

@ -65,11 +65,10 @@ impl SessionManager {
fn with_ui_connection<F>(&self, f: F) where F: FnOnce(&mut UiConnection) {
let mut ui_connection_opt = self.ui_connection.lock().unwrap();
match ui_connection_opt.as_mut() {
Some(ui_connection) => if ui_connection.is_valid {
if let Some(ui_connection) = ui_connection_opt.as_mut() {
if ui_connection.is_valid {
f(ui_connection);
}
None => {}
}
}
@ -110,10 +109,7 @@ impl SessionManager {
fn get_session_sender(&self, session_id: &usize) -> Option<Sender<SessionCommand>> {
let sessions = self.sessions.read().unwrap();
match sessions.get(session_id) {
Some(session_data) => Some(session_data.sender.clone()),
None => None
}
sessions.get(session_id).map(|session_data| session_data.sender.clone())
}
pub async fn send_command(&self, session_id: &usize, session_command: SessionCommand) -> bool {
@ -488,13 +484,11 @@ impl SessionManager {
//don't send msg if we already encrypted a file chunk (keep PSEC nonces synchronized)
if is_sending {
msg_queue.push(buff);
} else {
if let Err(e) = self.send_msg(session_id, &mut session_write, buff, &mut is_sending, &mut file_ack_sender).await {
} else if let Err(e) = self.send_msg(session_id, &mut session_write, buff, &mut is_sending, &mut file_ack_sender).await {
print_error!(e);
break;
}
}
}
SessionCommand::EncryptFileChunk { plain_text } => {
last_chunks_sizes.as_mut().unwrap().push(plain_text.len() as u32);
next_chunk = Some(session_write.encrypt(&plain_text, self.identity.read().unwrap().as_ref().unwrap().use_padding));
@ -505,7 +499,7 @@ impl SessionManager {
Ok(_) => {
file_ack_sender = Some(ack_sender);
//once the pre-encrypted chunk is sent, we can send the pending messages
while msg_queue.len() > 0 {
while !msg_queue.is_empty() {
let msg = msg_queue.remove(0);
if let Err(e) = self.send_msg(session_id, &mut session_write, msg, &mut is_sending, &mut file_ack_sender).await {
print_error!(e);
@ -594,7 +588,7 @@ impl SessionManager {
outgoing,
peer_public_key,
ip,
sender: sender,
sender,
files_download: None,
};
let mut session_id = None;
@ -675,8 +669,7 @@ impl SessionManager {
}
let mut loaded_contacts = self.loaded_contacts.write().unwrap();
match loaded_contacts.get_mut(&session_id) {
Some(contact) => {
if let Some(contact) = loaded_contacts.get_mut(&session_id) {
if contact.seen != seen {
match self.identity.read().unwrap().as_ref().unwrap().set_contact_seen(&contact.uuid, seen) {
Ok(_) => contact.seen = seen,
@ -684,8 +677,6 @@ impl SessionManager {
}
}
}
None => {}
}
}
pub fn add_contact(&self, session_id: usize) -> Result<(), rusqlite::Error> {
@ -734,10 +725,10 @@ impl SessionManager {
}
pub fn store_file(&self, session_id: &usize, data: &[u8]) -> Result<Uuid, rusqlite::Error> {
self.identity.read().unwrap().as_ref().unwrap().store_file(match self.loaded_contacts.read().unwrap().get(session_id) {
Some(contact) => Some(contact.uuid),
None => None
}, data)
self.identity.read().unwrap().as_ref().unwrap().store_file(
self.loaded_contacts.read().unwrap().get(session_id).map(|contact| contact.uuid),
data
)
}
pub fn load_msgs(&self, session_id: &usize, count: usize) -> Option<Vec<Message>> {
@ -824,8 +815,7 @@ impl SessionManager {
}
*identity_guard = identity;
if identity_guard.is_some() { //login
match identity_guard.as_ref().unwrap().load_contacts() {
Some(contacts) => {
if let Some(contacts) = identity_guard.as_ref().unwrap().load_contacts() {
let mut loaded_contacts = self.loaded_contacts.write().unwrap();
let mut session_counter = self.session_counter.write().unwrap();
let mut not_seen = self.not_seen.write().unwrap();
@ -836,9 +826,7 @@ impl SessionManager {
loaded_contacts.insert(*session_counter, contact);
self.pending_msgs.lock().unwrap().insert(*session_counter, Vec::new());
*session_counter += 1;
})
}
None => {}
});
}
}
}

View File

@ -1,4 +1,4 @@
use std::{fmt::Display, iter::FromIterator, net::{IpAddr, TcpStream}, str::from_utf8};
use std::{fmt::Display, net::{IpAddr, TcpStream}, str::from_utf8};
use tungstenite::{WebSocket, protocol::Role, Message};
use uuid::Uuid;
use crate::{identity, print_error, protocol, session_manager::{LargeFileDownload, LargeFilesDownload}, utils::to_uuid_bytes};
@ -11,7 +11,7 @@ pub struct UiConnection{
impl UiConnection {
pub fn new(websocket: WebSocket<TcpStream>) -> UiConnection {
UiConnection {
websocket: websocket,
websocket,
is_valid: true
}
}
@ -26,14 +26,14 @@ impl UiConnection {
self.write_message(format!("{} {}", command, session_id));
}
fn data_list<T: Display>(command: &str, data: Vec<T>) -> String {
command.to_string()+&String::from_iter(data.into_iter().map(|i| {
command.to_string()+&data.into_iter().map(|i| {
format!(" {}", i)
}))
}).collect::<String>()
}
pub fn on_ask_large_files(&mut self, session_id: &usize, files: &Vec<LargeFileDownload>, download_location: &str) {
pub fn on_ask_large_files(&mut self, session_id: &usize, files: &[LargeFileDownload], download_location: &str) {
let mut s = format!("ask_large_files {} {}", session_id, base64::encode(download_location));
files.into_iter().for_each(|file| {
files.iter().for_each(|file| {
s.push_str(&format!(
" {} {}",
base64::encode(&file.file_name),
@ -100,9 +100,9 @@ impl UiConnection {
pub fn set_as_contact(&mut self, session_id: usize, name: &str, verified: bool, fingerprint: &str) {
self.write_message(format!("is_contact {} {} {} {}", session_id, verified, fingerprint, name));
}
pub fn load_msgs(&mut self, session_id: &usize, msgs: &Vec<identity::Message>) {
pub fn load_msgs(&mut self, session_id: &usize, msgs: &[identity::Message]) {
let mut s = format!("load_msgs {}", session_id);
msgs.into_iter().rev().for_each(|message| {
msgs.iter().rev().for_each(|message| {
match message.data[0] {
protocol::Headers::MESSAGE => match from_utf8(&message.data[1..]) {
Ok(msg) => s.push_str(&format!(" m {} {} {}", message.outgoing, message.timestamp, base64::encode(msg))),

View File

@ -1,4 +1,4 @@
use std::{convert::TryInto, time::{SystemTime, UNIX_EPOCH}, path::PathBuf};
use std::{convert::TryInto, time::{SystemTime, UNIX_EPOCH}, path::Path};
use uuid::Bytes;
use crate::print_error;
@ -24,7 +24,7 @@ pub fn get_unix_timestamp_sec() -> u64 {
SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()
}
pub fn get_not_used_path(file_name: &str, parent_directory: &PathBuf) -> String {
pub fn get_not_used_path(file_name: &str, parent_directory: &Path) -> String {
let has_extension = file_name.matches('.').count() > 0;
let mut path = parent_directory.join(&file_name);
let mut n = 1;