]> Untitled Git - lemmy.git/commitdiff
Fix concatenation of audio captcha wav files (#3350)
authorDominic Mazzoni <dmazzoni@gmail.com>
Fri, 30 Jun 2023 10:36:38 +0000 (03:36 -0700)
committerGitHub <noreply@github.com>
Fri, 30 Jun 2023 10:36:38 +0000 (12:36 +0200)
* Fix concatenation of audio captcha wav files

* Log errors rather than crashing

* Return Result from captcha_as_wav_base64

* Change to return LemmyError

* Check for wav write error, format

* Remove unused import

* Rewrite to avoid clippy warnings

crates/api/Cargo.toml
crates/api/src/lib.rs
crates/api/src/local_user/get_captcha.rs

index ca792809bed869ec39a4bbc28e960bfb4245e9c7..be3065e4df688f6f29b7e4c8f1b1f2f51feb1d2a 100644 (file)
@@ -30,6 +30,7 @@ captcha = { workspace = true }
 anyhow = { workspace = true }
 tracing = { workspace = true }
 chrono = { workspace = true }
+wav = "1.0.0"
 
 [dev-dependencies]
 serial_test = { workspace = true }
index 615a8a3144fdea49e8d7bca4388a79c8c05acd23..7ac3cec726faa2eabe956635bb8983b6aa573c81 100644 (file)
@@ -3,6 +3,7 @@ use captcha::Captcha;
 use lemmy_api_common::{context::LemmyContext, utils::local_site_to_slur_regex};
 use lemmy_db_schema::source::local_site::LocalSite;
 use lemmy_utils::{error::LemmyError, utils::slurs::check_slurs};
+use std::io::Cursor;
 
 mod comment;
 mod comment_report;
@@ -22,18 +23,42 @@ pub trait Perform {
 }
 
 /// Converts the captcha to a base64 encoded wav audio file
-pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
+pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> Result<String, LemmyError> {
   let letters = captcha.as_wav();
 
-  let mut concat_letters: Vec<u8> = Vec::new();
-
+  // Decode each wav file, concatenate the samples
+  let mut concat_samples: Vec<i16> = Vec::new();
+  let mut any_header: Option<wav::Header> = None;
   for letter in letters {
-    let bytes = letter.unwrap_or_default();
-    concat_letters.extend(bytes);
+    let mut cursor = Cursor::new(letter.unwrap_or_default());
+    let (header, samples) = wav::read(&mut cursor)?;
+    any_header = Some(header);
+    if let Some(samples16) = samples.as_sixteen() {
+      concat_samples.extend(samples16);
+    } else {
+      return Err(LemmyError::from_message("couldnt_create_audio_captcha"));
+    }
+  }
+
+  // Encode the concatenated result as a wav file
+  let mut output_buffer = Cursor::new(vec![]);
+  let header = match any_header {
+    Some(header) => header,
+    None => return Err(LemmyError::from_message("couldnt_create_audio_captcha")),
+  };
+  let wav_write_result = wav::write(
+    header,
+    &wav::BitDepth::Sixteen(concat_samples),
+    &mut output_buffer,
+  );
+  if let Err(e) = wav_write_result {
+    return Err(LemmyError::from_error_message(
+      e,
+      "couldnt_create_audio_captcha",
+    ));
   }
 
-  // Convert to base64
-  base64::encode(concat_letters)
+  Ok(base64::encode(output_buffer.into_inner()))
 }
 
 /// Check size of report and remove whitespace
index 1330442488ccf48b56eaa1652c20f069ff862b72..92653cfc6c1c7a16ca2df8eb1b70b97861128641 100644 (file)
@@ -33,7 +33,7 @@ impl Perform for GetCaptcha {
 
     let png = captcha.as_base64().expect("failed to generate captcha");
 
-    let wav = captcha_as_wav_base64(&captcha);
+    let wav = captcha_as_wav_base64(&captcha)?;
 
     let captcha_form: CaptchaAnswerForm = CaptchaAnswerForm { answer };
     // Stores the captcha item in the db