From 9eb21bb6a3887a70aaba8239df7e95b2b5765207 Mon Sep 17 00:00:00 2001 From: yggverse Date: Wed, 19 Mar 2025 15:06:53 +0200 Subject: [PATCH] Revert "hold raw header string" This reverts commit 5bb52fbd8c5aec9596c02ac641f10606407f0cd2. --- Cargo.toml | 2 +- src/client/connection/response/certificate.rs | 52 +++------------ .../connection/response/certificate/error.rs | 10 +-- src/client/connection/response/failure.rs | 7 -- .../connection/response/failure/permanent.rs | 60 ++++------------- .../connection/response/failure/temporary.rs | 60 ++++------------- src/client/connection/response/input.rs | 36 ++-------- src/client/connection/response/input/error.rs | 16 ++--- src/client/connection/response/redirect.rs | 24 ++----- src/client/connection/response/success.rs | 65 ++++++------------- .../connection/response/success/error.rs | 24 +++---- 11 files changed, 78 insertions(+), 278 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 442d0ee..54dd4b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ggemini" -version = "0.18.0" +version = "0.17.3" edition = "2024" license = "MIT" readme = "README.md" diff --git a/src/client/connection/response/certificate.rs b/src/client/connection/response/certificate.rs index 6b9e774..160e2f0 100644 --- a/src/client/connection/response/certificate.rs +++ b/src/client/connection/response/certificate.rs @@ -1,28 +1,19 @@ pub mod error; pub use error::Error; -const REQUIRED: (u8, &str) = (60, "Certificate required"); -const NOT_AUTHORIZED: (u8, &str) = (61, "Certificate not authorized"); -const NOT_VALID: (u8, &str) = (62, "Certificate not valid"); +const REQUIRED: (u8, &str) = (10, "Certificate required"); +const NOT_AUTHORIZED: (u8, &str) = (11, "Certificate not authorized"); +const NOT_VALID: (u8, &str) = (11, "Certificate not valid"); /// 6* status code group /// https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates pub enum Certificate { /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-60 - Required { - header: String, - message: Option, - }, + Required { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-61-certificate-not-authorized - NotAuthorized { - header: String, - message: Option, - }, + NotAuthorized { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-62-certificate-not-valid - NotValid { - header: String, - message: Option, - }, + NotValid { message: Option }, } impl Certificate { @@ -31,14 +22,7 @@ impl Certificate { /// Create new `Self` from buffer include header bytes pub fn from_utf8(buffer: &[u8]) -> Result { use std::str::FromStr; - let len = buffer.len(); - match std::str::from_utf8( - &buffer[..if len > super::HEADER_LEN { - super::HEADER_LEN - } else { - len - }], - ) { + match std::str::from_utf8(buffer) { Ok(header) => Self::from_str(header), Err(e) => Err(Error::Utf8Error(e)), } @@ -55,20 +39,11 @@ impl Certificate { .0 } - pub fn header(&self) -> &str { - match self { - Self::Required { header, .. } - | Self::NotAuthorized { header, .. } - | Self::NotValid { header, .. } => header, - } - .as_str() - } - pub fn message(&self) -> Option<&str> { match self { - Self::Required { message, .. } - | Self::NotAuthorized { message, .. } - | Self::NotValid { message, .. } => message, + Self::Required { message } => message, + Self::NotAuthorized { message } => message, + Self::NotValid { message } => message, } .as_deref() } @@ -92,25 +67,18 @@ impl std::fmt::Display for Certificate { impl std::str::FromStr for Certificate { type Err = Error; fn from_str(header: &str) -> Result { - let len = header.len(); - if len > super::HEADER_LEN { - return Err(Error::HeaderLen(len)); - } if let Some(postfix) = header.strip_prefix("60") { return Ok(Self::Required { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("61") { return Ok(Self::NotAuthorized { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("62") { return Ok(Self::NotValid { - header: header.to_string(), message: message(postfix), }); } diff --git a/src/client/connection/response/certificate/error.rs b/src/client/connection/response/certificate/error.rs index 62f17d1..5cf1cf6 100644 --- a/src/client/connection/response/certificate/error.rs +++ b/src/client/connection/response/certificate/error.rs @@ -6,7 +6,6 @@ use std::{ #[derive(Debug)] pub enum Error { Code, - HeaderLen(usize), Utf8Error(Utf8Error), } @@ -14,14 +13,7 @@ impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result { match self { Self::Code => { - write!(f, "Unexpected status code") - } - Self::HeaderLen(l) => { - write!( - f, - "Header length reached protocol limit ({l} of {} bytes max)", - super::super::HEADER_LEN - ) + write!(f, "Status code error") } Self::Utf8Error(e) => { write!(f, "UTF-8 error: {e}") diff --git a/src/client/connection/response/failure.rs b/src/client/connection/response/failure.rs index 8e85e84..40c8abf 100644 --- a/src/client/connection/response/failure.rs +++ b/src/client/connection/response/failure.rs @@ -45,13 +45,6 @@ impl Failure { } } - pub fn header(&self) -> &str { - match self { - Self::Permanent(permanent) => permanent.header(), - Self::Temporary(temporary) => temporary.header(), - } - } - pub fn message(&self) -> Option<&str> { match self { Self::Permanent(permanent) => permanent.message(), diff --git a/src/client/connection/response/failure/permanent.rs b/src/client/connection/response/failure/permanent.rs index e33ea13..e2ab9e0 100644 --- a/src/client/connection/response/failure/permanent.rs +++ b/src/client/connection/response/failure/permanent.rs @@ -10,30 +10,15 @@ const BAD_REQUEST: (u8, &str) = (59, "bad-request"); /// https://geminiprotocol.net/docs/protocol-specification.gmi#permanent-failure pub enum Permanent { /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-50 - Default { - header: String, - message: Option, - }, + Default { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-51-not-found - NotFound { - header: String, - message: Option, - }, + NotFound { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-52-gone - Gone { - header: String, - message: Option, - }, + Gone { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-53-proxy-request-refused - ProxyRequestRefused { - header: String, - message: Option, - }, + ProxyRequestRefused { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-59-bad-request - BadRequest { - header: String, - message: Option, - }, + BadRequest { message: Option }, } impl Permanent { @@ -42,14 +27,7 @@ impl Permanent { /// Create new `Self` from buffer include header bytes pub fn from_utf8(buffer: &[u8]) -> Result { use std::str::FromStr; - let len = buffer.len(); - match std::str::from_utf8( - &buffer[..if len > super::super::HEADER_LEN { - super::super::HEADER_LEN - } else { - len - }], - ) { + match std::str::from_utf8(buffer) { Ok(header) => Self::from_str(header), Err(e) => Err(Error::Utf8Error(e)), } @@ -68,24 +46,13 @@ impl Permanent { .0 } - pub fn header(&self) -> &str { - match self { - Self::Default { header, .. } - | Self::NotFound { header, .. } - | Self::Gone { header, .. } - | Self::ProxyRequestRefused { header, .. } - | Self::BadRequest { header, .. } => header, - } - .as_str() - } - pub fn message(&self) -> Option<&str> { match self { - Self::Default { message, .. } - | Self::NotFound { message, .. } - | Self::Gone { message, .. } - | Self::ProxyRequestRefused { message, .. } - | Self::BadRequest { message, .. } => message, + Self::Default { message } => message, + Self::NotFound { message } => message, + Self::Gone { message } => message, + Self::ProxyRequestRefused { message } => message, + Self::BadRequest { message } => message, } .as_deref() } @@ -113,31 +80,26 @@ impl std::str::FromStr for Permanent { fn from_str(header: &str) -> Result { if let Some(postfix) = header.strip_prefix("50") { return Ok(Self::Default { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("51") { return Ok(Self::NotFound { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("52") { return Ok(Self::Gone { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("53") { return Ok(Self::ProxyRequestRefused { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("59") { return Ok(Self::BadRequest { - header: header.to_string(), message: message(postfix), }); } diff --git a/src/client/connection/response/failure/temporary.rs b/src/client/connection/response/failure/temporary.rs index 21fc2b4..768bdcd 100644 --- a/src/client/connection/response/failure/temporary.rs +++ b/src/client/connection/response/failure/temporary.rs @@ -10,30 +10,15 @@ const SLOW_DOWN: (u8, &str) = (44, "Slow down"); /// https://geminiprotocol.net/docs/protocol-specification.gmi#temporary-failure pub enum Temporary { /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-40 - Default { - header: String, - message: Option, - }, + Default { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-41-server-unavailable - ServerUnavailable { - header: String, - message: Option, - }, + ServerUnavailable { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-42-cgi-error - CgiError { - header: String, - message: Option, - }, + CgiError { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-43-proxy-error - ProxyError { - header: String, - message: Option, - }, + ProxyError { message: Option }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-44-slow-down - SlowDown { - header: String, - message: Option, - }, + SlowDown { message: Option }, } impl Temporary { @@ -42,14 +27,7 @@ impl Temporary { /// Create new `Self` from buffer include header bytes pub fn from_utf8(buffer: &[u8]) -> Result { use std::str::FromStr; - let len = buffer.len(); - match std::str::from_utf8( - &buffer[..if len > super::super::HEADER_LEN { - super::super::HEADER_LEN - } else { - len - }], - ) { + match std::str::from_utf8(buffer) { Ok(header) => Self::from_str(header), Err(e) => Err(Error::Utf8Error(e)), } @@ -68,24 +46,13 @@ impl Temporary { .0 } - pub fn header(&self) -> &str { - match self { - Self::Default { header, .. } - | Self::ServerUnavailable { header, .. } - | Self::CgiError { header, .. } - | Self::ProxyError { header, .. } - | Self::SlowDown { header, .. } => header, - } - .as_str() - } - pub fn message(&self) -> Option<&str> { match self { - Self::Default { message, .. } - | Self::ServerUnavailable { message, .. } - | Self::CgiError { message, .. } - | Self::ProxyError { message, .. } - | Self::SlowDown { message, .. } => message, + Self::Default { message } => message, + Self::ServerUnavailable { message } => message, + Self::CgiError { message } => message, + Self::ProxyError { message } => message, + Self::SlowDown { message } => message, } .as_deref() } @@ -113,31 +80,26 @@ impl std::str::FromStr for Temporary { fn from_str(header: &str) -> Result { if let Some(postfix) = header.strip_prefix("40") { return Ok(Self::Default { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("41") { return Ok(Self::ServerUnavailable { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("42") { return Ok(Self::CgiError { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("43") { return Ok(Self::ProxyError { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("44") { return Ok(Self::SlowDown { - header: header.to_string(), message: message(postfix), }); } diff --git a/src/client/connection/response/input.rs b/src/client/connection/response/input.rs index 78aa3a1..b62276b 100644 --- a/src/client/connection/response/input.rs +++ b/src/client/connection/response/input.rs @@ -5,14 +5,8 @@ const DEFAULT: (u8, &str) = (10, "Input"); const SENSITIVE: (u8, &str) = (11, "Sensitive input"); pub enum Input { - Default { - header: String, - message: Option, - }, - Sensitive { - header: String, - message: Option, - }, + Default { message: Option }, + Sensitive { message: Option }, } impl Input { @@ -21,14 +15,7 @@ impl Input { /// Create new `Self` from buffer include header bytes pub fn from_utf8(buffer: &[u8]) -> Result { use std::str::FromStr; - let len = buffer.len(); - match std::str::from_utf8( - &buffer[..if len > super::HEADER_LEN { - super::HEADER_LEN - } else { - len - }], - ) { + match std::str::from_utf8(buffer) { Ok(header) => Self::from_str(header), Err(e) => Err(Error::Utf8Error(e)), } @@ -44,16 +31,10 @@ impl Input { .0 } - pub fn header(&self) -> &str { - match self { - Self::Default { header, .. } | Self::Sensitive { header, .. } => header, - } - .as_str() - } - pub fn message(&self) -> Option<&str> { match self { - Self::Default { message, .. } | Self::Sensitive { message, .. } => message, + Self::Default { message } => message, + Self::Sensitive { message } => message, } .as_deref() } @@ -76,22 +57,17 @@ impl std::fmt::Display for Input { impl std::str::FromStr for Input { type Err = Error; fn from_str(header: &str) -> Result { - if header.len() > super::HEADER_LEN { - return Err(Error::HeaderLen(header.len())); - } if let Some(postfix) = header.strip_prefix("10") { return Ok(Self::Default { - header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("11") { return Ok(Self::Sensitive { - header: header.to_string(), message: message(postfix), }); } - Err(Error::Code) + Err(Error::Protocol) } } diff --git a/src/client/connection/response/input/error.rs b/src/client/connection/response/input/error.rs index 62f17d1..ae589e8 100644 --- a/src/client/connection/response/input/error.rs +++ b/src/client/connection/response/input/error.rs @@ -5,27 +5,19 @@ use std::{ #[derive(Debug)] pub enum Error { - Code, - HeaderLen(usize), + Protocol, Utf8Error(Utf8Error), } impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result { match self { - Self::Code => { - write!(f, "Unexpected status code") - } - Self::HeaderLen(l) => { - write!( - f, - "Header length reached protocol limit ({l} of {} bytes max)", - super::super::HEADER_LEN - ) - } Self::Utf8Error(e) => { write!(f, "UTF-8 error: {e}") } + Self::Protocol => { + write!(f, "Protocol error") + } } } } diff --git a/src/client/connection/response/redirect.rs b/src/client/connection/response/redirect.rs index b936944..2554fdf 100644 --- a/src/client/connection/response/redirect.rs +++ b/src/client/connection/response/redirect.rs @@ -8,9 +8,9 @@ const PERMANENT: (u8, &str) = (31, "Permanent redirect"); pub enum Redirect { /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-30-temporary-redirection - Temporary { header: String, target: String }, + Temporary { target: String }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-31-permanent-redirection - Permanent { header: String, target: String }, + Permanent { target: String }, } impl Redirect { @@ -19,14 +19,7 @@ impl Redirect { /// Create new `Self` from buffer include header bytes pub fn from_utf8(buffer: &[u8]) -> Result { use std::str::FromStr; - let len = buffer.len(); - match std::str::from_utf8( - &buffer[..if len > super::HEADER_LEN { - super::HEADER_LEN - } else { - len - }], - ) { + match std::str::from_utf8(buffer) { Ok(header) => Self::from_str(header), Err(e) => Err(Error::Utf8Error(e)), } @@ -94,15 +87,10 @@ impl Redirect { // Getters - pub fn header(&self) -> &str { - match self { - Self::Permanent { header, .. } | Self::Temporary { header, .. } => header, - } - } - pub fn target(&self) -> &str { match self { - Self::Permanent { target, .. } | Self::Temporary { target, .. } => target, + Self::Permanent { target } => target, + Self::Temporary { target } => target, } } } @@ -136,11 +124,9 @@ impl std::str::FromStr for Redirect { match regex.get(1) { Some(code) => match code.as_str() { "0" => Ok(Self::Temporary { - header: header.to_string(), target: target(regex.get(2))?, }), "1" => Ok(Self::Permanent { - header: header.to_string(), target: target(regex.get(2))?, }), _ => todo!(), diff --git a/src/client/connection/response/success.rs b/src/client/connection/response/success.rs index e9c240e..e5ad6f4 100644 --- a/src/client/connection/response/success.rs +++ b/src/client/connection/response/success.rs @@ -4,7 +4,7 @@ pub use error::Error; const DEFAULT: (u8, &str) = (20, "Success"); pub enum Success { - Default { header: String, mime: String }, + Default { mime: String }, // reserved for 2* codes } @@ -14,14 +14,7 @@ impl Success { /// Create new `Self` from buffer include header bytes pub fn from_utf8(buffer: &[u8]) -> Result { use std::str::FromStr; - let len = buffer.len(); - match std::str::from_utf8( - &buffer[..if len > super::HEADER_LEN { - super::HEADER_LEN - } else { - len - }], - ) { + match std::str::from_utf8(buffer) { Ok(header) => Self::from_str(header), Err(e) => Err(Error::Utf8Error(e)), } @@ -37,16 +30,9 @@ impl Success { // Getters - pub fn header(&self) -> &str { - match self { - Self::Default { header, .. } => header, - } - .as_str() - } - pub fn mime(&self) -> &str { match self { - Self::Default { mime, .. } => mime, + Self::Default { mime } => mime, } } } @@ -68,34 +54,25 @@ impl std::str::FromStr for Success { fn from_str(header: &str) -> Result { use glib::{Regex, RegexCompileFlags, RegexMatchFlags}; - if header.len() > super::HEADER_LEN { - return Err(Error::HeaderLen(header.len())); - } - - // * keep separator after code as expected by protocol - match header.strip_prefix("20") { - Some(postfix) => match Regex::split_simple( - r"^\s+([^\/]+\/[^\s;]+)", - postfix, - RegexCompileFlags::DEFAULT, - RegexMatchFlags::DEFAULT, - ) - .get(1) - { - Some(mime) => { - let mime = mime.trim(); - if mime.is_empty() { - Err(Error::ContentType) - } else { - Ok(Self::Default { - header: header.to_string(), - mime: mime.to_lowercase(), - }) - } + match Regex::split_simple( + r"^20\s([^\/]+\/[^\s;]+)", + header, + RegexCompileFlags::DEFAULT, + RegexMatchFlags::DEFAULT, + ) + .get(1) + { + Some(mime) => { + let mime = mime.trim(); + if mime.is_empty() { + Err(Error::Mime) + } else { + Ok(Self::Default { + mime: mime.to_lowercase(), + }) } - None => Err(Error::ContentType), - }, - None => Err(Error::Code), + } + None => Err(Error::Protocol), } } } diff --git a/src/client/connection/response/success/error.rs b/src/client/connection/response/success/error.rs index 7eaf2e0..2dbe363 100644 --- a/src/client/connection/response/success/error.rs +++ b/src/client/connection/response/success/error.rs @@ -5,31 +5,23 @@ use std::{ #[derive(Debug)] pub enum Error { - Code, - ContentType, - HeaderLen(usize), + Protocol, + Mime, Utf8Error(Utf8Error), } impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result { match self { - Self::Code => { - write!(f, "Unexpected status code") - } - Self::ContentType => { - write!(f, "Content type required") - } - Self::HeaderLen(l) => { - write!( - f, - "Header length reached protocol limit ({l} of {} bytes max)", - super::super::HEADER_LEN - ) - } Self::Utf8Error(e) => { write!(f, "UTF-8 error: {e}") } + Self::Protocol => { + write!(f, "Protocol error") + } + Self::Mime => { + write!(f, "MIME error") + } } } }