From d241e00fcfba0731118f5e6f6a0094c15d5ecd26 Mon Sep 17 00:00:00 2001 From: constantoine Date: Wed, 2 Nov 2022 11:29:04 +0100 Subject: [PATCH 1/3] Implement std::error::Error for totp-rs error types Signed-off-by: constantoine --- src/rfc.rs | 2 ++ src/url_error.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/rfc.rs b/src/rfc.rs index 34204a7..5863bb6 100644 --- a/src/rfc.rs +++ b/src/rfc.rs @@ -14,6 +14,8 @@ pub enum Rfc6238Error { SecretTooSmall(usize), } +impl std::error::Error for Rfc6238Error {} + impl std::fmt::Display for Rfc6238Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/src/url_error.rs b/src/url_error.rs index 76ef73f..3d63de2 100644 --- a/src/url_error.rs +++ b/src/url_error.rs @@ -22,6 +22,8 @@ pub enum TotpUrlError { AccountNameDecoding(String), } +impl std::error::Error for TotpUrlError {} + impl std::fmt::Display for TotpUrlError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { From d901803ce5ae3d54331def419abb0158798fa190 Mon Sep 17 00:00:00 2001 From: constantoine Date: Wed, 2 Nov 2022 11:32:10 +0100 Subject: [PATCH 2/3] Better error handling -Implement Display for TOTP -Make get_qr() Error type be a string Signed-off-by: constantoine --- src/lib.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 329002d..f50edf4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -170,6 +170,34 @@ impl> PartialEq for TOTP { } } +#[cfg(feature = "otpauth")] +impl core::fmt::Display for TOTP { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "digits: {}; step: {}; alg: {}; issuer: <{}>({})", + self.digits, + self.step, + self.algorithm, + self.issuer.clone().unwrap_or_else(|| "None".to_string()), + self.account_name + ) + } +} + +#[cfg(not(feature = "otpauth"))] +impl core::fmt::Display for TOTP { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "digits: {}; step: {}; alg: {}", + self.digits, + self.step, + self.algorithm, + ) + } +} + #[cfg(all(feature = "gen_secret", not(feature = "otpauth")))] impl Default for TOTP { fn default() -> Self { @@ -529,28 +557,40 @@ impl> TOTP { /// /// It will also return an error in case it can't encode the qr into a png. This shouldn't happen unless either the qrcode library returns malformed data, or the image library doesn't encode the data correctly #[cfg(feature = "qr")] - pub fn get_qr(&self) -> Result> { + pub fn get_qr(&self) -> Result { use image::ImageEncoder; let url = self.get_url(); let mut vec = Vec::new(); - let qr = qrcodegen::QrCode::encode_text(&url, qrcodegen::QrCodeEcc::Medium)?; + + let qr: Result = match qrcodegen::QrCode::encode_text(&url, qrcodegen::QrCodeEcc::Medium) { + Ok(qr) => Ok(qr), + Err(err) => Err(err.to_string()) + }; + + if qr.is_err() { + return Err(qr.err().unwrap()); + } + + let code = qr?; // "+ 8 * 8" is here to add padding (the white border around the QRCode) // As some QRCode readers don't work without padding - let image_size = (qr.size() as u32) * 8 + 8 * 8; + let image_size = (code.size() as u32) * 8 + 8 * 8; - let canvas = self.get_qr_draw_canvas(qr); + let canvas = self.get_qr_draw_canvas(code); // Encode the canvas into a PNG let encoder = image::codecs::png::PngEncoder::new(&mut vec); - encoder.write_image( + match encoder.write_image( &canvas.into_raw(), image_size, image_size, image::ColorType::L8, - )?; - Ok(base64::encode(vec)) + ) { + Ok(_) => Ok(base64::encode(vec)), + Err(err) => Err(err.to_string()) + } } } From fb9ada36c2257ca02b7130a9a6c67f3c0d5a7be9 Mon Sep 17 00:00:00 2001 From: constantoine Date: Wed, 2 Nov 2022 11:33:26 +0100 Subject: [PATCH 3/3] cargo fmt Signed-off-by: constantoine --- src/lib.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f50edf4..3b1a9d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -191,9 +191,7 @@ impl core::fmt::Display for TOTP { write!( f, "digits: {}; step: {}; alg: {}", - self.digits, - self.step, - self.algorithm, + self.digits, self.step, self.algorithm, ) } } @@ -563,10 +561,11 @@ impl> TOTP { let url = self.get_url(); let mut vec = Vec::new(); - let qr: Result = match qrcodegen::QrCode::encode_text(&url, qrcodegen::QrCodeEcc::Medium) { - Ok(qr) => Ok(qr), - Err(err) => Err(err.to_string()) - }; + let qr: Result = + match qrcodegen::QrCode::encode_text(&url, qrcodegen::QrCodeEcc::Medium) { + Ok(qr) => Ok(qr), + Err(err) => Err(err.to_string()), + }; if qr.is_err() { return Err(qr.err().unwrap()); @@ -589,7 +588,7 @@ impl> TOTP { image::ColorType::L8, ) { Ok(_) => Ok(base64::encode(vec)), - Err(err) => Err(err.to_string()) + Err(err) => Err(err.to_string()), } } }