diff --git a/src/packet/data.rs b/src/packet/data.rs index dc98ae7..49230d4 100644 --- a/src/packet/data.rs +++ b/src/packet/data.rs @@ -4,3 +4,5 @@ pub mod name; pub mod opendir; pub mod status; pub mod handle; +pub mod attrs; +pub mod stat; diff --git a/src/packet/data/attrs.rs b/src/packet/data/attrs.rs new file mode 100644 index 0000000..0fe761b --- /dev/null +++ b/src/packet/data/attrs.rs @@ -0,0 +1,18 @@ +pub struct AttrsData { + id: u32, + attrs: u32, +} + +impl AttrsData { + pub fn new(id: u32) -> AttrsData { + let attrs: u32 = 0; + AttrsData { id: id, attrs: attrs } + } + + pub fn serialize(&self) -> Vec { + let mut serialized_data: Vec = Vec::new(); + serialized_data.extend(&self.id.to_be_bytes()); + serialized_data.extend(&self.attrs.to_be_bytes()); + serialized_data + } +} diff --git a/src/packet/data/stat.rs b/src/packet/data/stat.rs new file mode 100644 index 0000000..7af644e --- /dev/null +++ b/src/packet/data/stat.rs @@ -0,0 +1,17 @@ +use std::io::Read; + +pub struct StatData { + pub id: u32, + pub path: String, +} + +impl StatData { + pub fn deserialize(mut data_to_serialize: &[u8]) -> StatData { + let mut id: [u8; 4] = [0; 4]; + data_to_serialize.read(&mut id).expect("Failed to read id."); + let id: u32 = u32::from_be_bytes(id); + let path: String = + crate::packet::types::string::String::deserialize(data_to_serialize).content; + StatData { id: id, path: path } + } +} diff --git a/src/packet/dispatch.rs b/src/packet/dispatch.rs index 2d0251a..16525dc 100644 --- a/src/packet/dispatch.rs +++ b/src/packet/dispatch.rs @@ -7,21 +7,28 @@ use crate::constants::SSH_FXP_OPENDIR; use crate::constants::SSH_FXP_REALPATH; use crate::constants::SSH_FXP_STATUS; use crate::constants::SSH_FXP_VERSION; +use crate::constants::SSH_FXP_ATTRS; +use crate::constants::SSH_FXP_STAT; +use crate::constants::SSH_FXP_LSTAT; use crate::constants::SSH_FX_FAILURE; use crate::constants::SSH_FX_NO_SUCH_FILE; +use crate::constants::SSH_FX_OP_UNSUPPORTED; use crate::handle::DirectoryHandle; +use crate::packet::data::handle::HandleData; use crate::packet::data::name::NameData; use crate::packet::data::opendir::OpendirData; use crate::packet::data::realpath::RealpathData; use crate::packet::data::status::StatusData; use crate::packet::data::version::VersionData; -use crate::packet::data::handle::HandleData; +use crate::packet::data::attrs::AttrsData; +use crate::packet::data::stat::StatData; use crate::packet::header::PacketHeader; use crate::packet::Packet; use crate::php; use crate::sftp::realpath; use std::collections::HashMap; +use std::io::Read; use std::io::{BufWriter, Write}; pub fn loop_of_dispatch(nextcloud_folder: &str, user: &str) { @@ -44,8 +51,35 @@ pub fn dispatch_packet( SSH_FXP_REALPATH => dispatch_realpath_request(packet), SSH_FXP_OPENDIR => { dispatch_opendir_request(packet, directory_handles, nextcloud_folder, user) + }, + SSH_FXP_STAT => { + dispatch_stat_request(packet, nextcloud_folder, user) + }, + SSH_FXP_LSTAT => { + dispatch_stat_request(packet, nextcloud_folder, user) + }, + _ => { + eprintln!("{} not implemented.", packet.packet_header.type_packet); + let mut id: [u8; 4] = [0; 4]; + let mut packet_data: &[u8] = &packet.data; + packet_data + .read(&mut id) + .expect("Id for the last request was not provided."); + let id: u32 = u32::from_be_bytes(id); + Packet { + packet_header: PacketHeader { + length: 0, + type_packet: SSH_FXP_STATUS, + }, + data: StatusData { + id: id, + status_code: SSH_FX_OP_UNSUPPORTED, + error_message: "The operation {} is not supported yet.".to_string(), + lang: "en_US".to_string(), + } + .serialize(), + } } - _ => panic!("{} not implemented.", packet.packet_header.type_packet), }; let serialized_response = response.serialize(); eprintln!("Writing response."); @@ -56,6 +90,33 @@ pub fn dispatch_packet( buff_stdout.flush().expect("Unable to flush stdout."); } +fn dispatch_stat_request(packet: Packet, nextcloud_folder: &str, user: &str) -> Packet { + let stat_data: StatData = StatData::deserialize(&packet.data); + if !php::check_if_exists(&stat_data.path, &user, &nextcloud_folder) { + Packet { + packet_header: PacketHeader { + length: 0, + type_packet: SSH_FXP_STATUS, + }, + data: StatusData { + id: stat_data.id, + status_code: SSH_FX_NO_SUCH_FILE, + error_message: "No such file or directory.".to_string(), + lang: "en_US".to_string(), + } + .serialize(), + } + } else { + Packet { + packet_header: PacketHeader { + length: 0, + type_packet: SSH_FXP_ATTRS, + }, + data: AttrsData::new(stat_data.id).serialize(), + } + } +} + fn dispatch_opendir_request( packet: Packet, directory_handles: &mut HashMap,