diff --git a/src/magick.rs b/src/magick.rs index ebf0d48..65ab524 100644 --- a/src/magick.rs +++ b/src/magick.rs @@ -54,6 +54,7 @@ pub(crate) fn convert_bytes_read( &[ "convert", "-", + "-strip", format!("{}:-", format.to_magick_format()).as_str(), ], )?; diff --git a/src/upload_manager.rs b/src/upload_manager.rs index 6cab900..0f827ca 100644 --- a/src/upload_manager.rs +++ b/src/upload_manager.rs @@ -703,6 +703,7 @@ impl UploadManagerSession { let (content_type, validated_reader) = crate::validate::validate_image_bytes( bytes_mut.freeze(), self.manager.inner.format.clone(), + validate, ) .await?; @@ -741,6 +742,7 @@ impl UploadManagerSession { let (content_type, validated_reader) = crate::validate::validate_image_bytes( bytes_mut.freeze(), self.manager.inner.format.clone(), + true, ) .await?; diff --git a/src/validate.rs b/src/validate.rs index d8c6d24..ee13d83 100644 --- a/src/validate.rs +++ b/src/validate.rs @@ -11,13 +11,57 @@ pub(crate) fn video_mp4() -> mime::Mime { "video/mp4".parse().unwrap() } +struct UnvalidatedBytes { + bytes: Bytes, + written: usize, +} + +impl UnvalidatedBytes { + fn new(bytes: Bytes) -> Self { + UnvalidatedBytes { bytes, written: 0 } + } + + fn boxed(self) -> Box { + Box::new(self) + } +} + +impl AsyncRead for UnvalidatedBytes { + fn poll_read( + mut self: std::pin::Pin<&mut Self>, + _cx: &mut std::task::Context<'_>, + buf: &mut tokio::io::ReadBuf<'_>, + ) -> std::task::Poll> { + let bytes_to_write = (self.bytes.len() - self.written).min(buf.remaining()); + if bytes_to_write > 0 { + let end = self.written + bytes_to_write; + buf.put_slice(&self.bytes[self.written..end]); + self.written = end; + } + std::task::Poll::Ready(Ok(())) + } +} + #[instrument(name = "Validate image", skip(bytes))] pub(crate) async fn validate_image_bytes( bytes: Bytes, prescribed_format: Option, + validate: bool, ) -> Result<(mime::Mime, Box), Error> { let input_type = crate::magick::input_type_bytes(bytes.clone()).await?; + if !validate { + let mime_type = match input_type { + ValidInputType::Gif => video_mp4(), + ValidInputType::Mp4 => mime::IMAGE_GIF, + ValidInputType::Jpeg => mime::IMAGE_JPEG, + ValidInputType::Png => mime::IMAGE_PNG, + ValidInputType::Webp => image_webp(), + }; + + return Ok((mime_type, UnvalidatedBytes::new(bytes).boxed())); + } + match (prescribed_format, input_type) { (_, ValidInputType::Gif) => Ok(( video_mp4(),