Introduce FTP support, modify http1 documentation and bump version number

This commit is contained in:
abbie 2022-03-13 11:36:10 +00:00
parent f3279b6188
commit f407dec4f8
No known key found for this signature in database
GPG key ID: 04DDE463F9200F87
6 changed files with 117 additions and 1 deletions

View file

@ -1,7 +1,7 @@
[package] [package]
name = "packeteer" name = "packeteer"
description = "An attempt at a Rust library that can be used to assist in programmatically analysing, serving and handling received protocol packets." description = "An attempt at a Rust library that can be used to assist in programmatically analysing, serving and handling received protocol packets."
version = "0.2.2" version = "0.3.0"
edition = "2021" edition = "2021"
authors = ["Celeste <colean@colean.cc>"] authors = ["Celeste <colean@colean.cc>"]
license = "LGPL-3.0-or-later" license = "LGPL-3.0-or-later"
@ -17,5 +17,6 @@ all-features = true
[features] [features]
http1 = [] http1 = []
gemini = [] gemini = []
ftp = []
[dependencies] [dependencies]

2
README
View file

@ -5,6 +5,8 @@ Packeteer is a library that can handle structurally organising protocol packets
Supported protocols Supported protocols
----------------------- -----------------------
* HTTP/1.x * HTTP/1.x
* Gemini
* FTP
What Packeteer is not What Packeteer is not
------------------------- -------------------------

View file

@ -4,6 +4,8 @@
<h2>Supported protocols</h2> <h2>Supported protocols</h2>
<ul> <ul>
<li>HTTP/1.x</li> <li>HTTP/1.x</li>
<li>Gemini</li>
<li>FTP</li>
</ul> </ul>
<h2>What Packeteer is not</h2> <h2>What Packeteer is not</h2>

106
src/ftp.rs Normal file
View file

@ -0,0 +1,106 @@
//! A module for handling FTP operations.
//! It contains structures for FTP requests and responses as well as functions for generating, unpacking and constructing them.
// unwrap_url not required as we aren't unwrapping Url structures.
use super::{Url, wrap_url};
use std::str::FromStr;
/// A structure for FTP requests.
/// Generated with packeteer::ftp::generate_request
#[derive(Debug)]
pub struct FTPRequest {
pub url: Url,
pub command: String,
pub arguments: Vec<String>,
}
/// A structure for FTP responses.
/// Generated with packeteer::ftp::generate_response
#[derive(Debug)]
pub struct FTPResponse {
pub code: i32,
pub message: String,
}
/// A function for generating FTPRequest structures.
/// The command and arguments are split for convenience.
/// There is also a URL element. FTP doesn't have any place to put a URL however it is here to make thing easier for clients handling multiple servers simulatenously and/or proxies.
pub fn generate_request(url: &str, cmd: &str) -> FTPRequest {
let wurl = wrap_url(url);
let split: Vec<&str> = cmd.split(" ").collect();
let mut args: Vec<String> = vec![];
for v in &split {
if v != &split[0] {
args.push(v.to_string());
}
}
let req = FTPRequest { url: wurl, command: split[0].to_string(), arguments: args };
return req
}
/// A function for generating FTPResponse structures.
/// Messages associated to status codes are not provided by the module, unlike http1, and must be provided by the program using it.
/// Also unlike http1, ftp doesn't automatically check status code for integrity.
pub fn generate_response(code: i32, message: &str) -> FTPResponse {
let res = FTPResponse { code: code, message: message.to_string() };
return res
}
/// A function for converting FTPRequest structures into an FTP request string.
/// Unpacking functions are simply taking the data stored in the structure and concatenating it into a string so nothing changes apart from the conversion.
pub fn unpack_request(req: FTPRequest) -> String {
let mut string = format!("{}", req.command);
let empty: Vec<String> = vec![];
if req.arguments != empty {
for v in req.arguments {
string = format!("{} {}", string, v);
}
}
string = format!("{}\r\n", string);
return string.to_string()
}
/// A function for converting FTPResponse structures into FTP response strings.
/// Unpacking functions are simply taking the data stored in the structure and concatenating it into a string so nothing changes apart from the conversion.
pub fn unpack_response(res: FTPResponse) -> String {
let string = format!("{} {}\r\n", res.code, res.message);
return string
}
/// A fucntion for converting FTP request strings into FTPRequest.
/// The arguments are split, similarly to generate_request.
/// Since FTPRequest features a Url field, it will be set to an invalid address.
/// Construction functions aim to be as transparent as possible so apart from turning it into a structure, the request stays relatively unchanged.
pub fn construct_request(req: &str) -> FTPRequest {
let split: Vec<&str> = req.split("\r\n").collect();
let split1: Vec<&str> = split[0].split(" ").collect();
let string = split1[0];
let mut args: Vec<String> = vec![];
for v in &split1 {
if v != &split1[0] {
args.push(v.to_string());
}
}
let freq = FTPRequest { url: wrap_url("ftp://packeteer.invalid/dont-process-me"), command: string.to_string(), arguments: args };
return freq
}
/// A function for converting FTP response strings into FTPResponse.
/// Construction functions aim to be as transparent as possible so apart from turning it into a structure, the request stays relatively unchanged.
pub fn construct_response(res: &str) -> FTPResponse {
let split: Vec<&str> = res.split("\r\n").collect();
let split1: Vec<&str> = split[0].split(" ").collect();
let n: i32 = FromStr::from_str(split1[0]).unwrap();
let mut message = "".to_string();
for v in &split1 {
if v != &split1[0] {
if message == "".to_string() {
message = v.to_string();
} else {
message = format!("{} {}", message, v);
}
}
}
let resp = FTPResponse { code: n, message: message.to_string() };
return resp
}

View file

@ -34,6 +34,7 @@ pub fn generate_request(method: &str, host: &str, location: &str, body: &str) ->
} }
/// A function for generating Http1Response structures. /// A function for generating Http1Response structures.
/// By default, packeteer generates HTTP/1.1 responses. /// By default, packeteer generates HTTP/1.1 responses.
/// Invalid status codes will automatically be turned into code 500 (Internal Server Error)
pub fn generate_response(code: i32, body: &str) -> Http1Response { pub fn generate_response(code: i32, body: &str) -> Http1Response {
let mut xcode = code; let mut xcode = code;
if code_to_string(xcode) == "500 Internal Server Error" { if code_to_string(xcode) == "500 Internal Server Error" {
@ -75,6 +76,7 @@ pub fn construct_request(request: &str) -> Http1Request {
} }
/// A function for converting HTTP/1.x response strings into Http1Response. /// A function for converting HTTP/1.x response strings into Http1Response.
/// Construction functions aim to be as transparent as possible so apart from turning it into a structure, the response stays relatively unchanged. /// Construction functions aim to be as transparent as possible so apart from turning it into a structure, the response stays relatively unchanged.
/// Responses passed here with invalid status codes will keep their invalid status code.
pub fn construct_response(response: &str) -> Http1Response { pub fn construct_response(response: &str) -> Http1Response {
let split = response.split("\r\n"); let split = response.split("\r\n");
let mut response = Http1Response { version: "".to_string(), status: "".to_string(), headers: vec![], body: "".to_string(), code: 0 }; let mut response = Http1Response { version: "".to_string(), status: "".to_string(), headers: vec![], body: "".to_string(), code: 0 };

View file

@ -82,3 +82,6 @@ pub mod http1;
#[cfg(feature = "gemini")] #[cfg(feature = "gemini")]
pub mod gemini; pub mod gemini;
#[cfg(feature = "ftp")]
pub mod ftp;