pict-rs/src/validate.rs

109 lines
3.6 KiB
Rust
Raw Normal View History

2021-10-21 01:13:39 +00:00
use crate::{
2023-02-04 23:32:36 +00:00
config::{ImageFormat, MediaConfiguration},
2022-03-29 16:04:56 +00:00
either::Either,
error::{Error, UploadError},
2023-02-04 23:32:36 +00:00
ffmpeg::{FileFormat, TranscodeOptions},
2022-03-29 16:04:56 +00:00
magick::ValidInputType,
2021-10-21 01:13:39 +00:00
};
use actix_web::web::Bytes;
use tokio::io::AsyncRead;
struct UnvalidatedBytes {
bytes: Bytes,
written: usize,
}
impl UnvalidatedBytes {
fn new(bytes: Bytes) -> Self {
UnvalidatedBytes { bytes, written: 0 }
}
}
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<std::io::Result<()>> {
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(()))
}
}
#[tracing::instrument(skip_all)]
pub(crate) async fn validate_bytes(
bytes: Bytes,
2023-02-04 23:32:36 +00:00
media: &MediaConfiguration,
validate: bool,
2021-10-23 17:35:07 +00:00
) -> Result<(ValidInputType, impl AsyncRead + Unpin), Error> {
2023-02-04 23:32:36 +00:00
let (details, input_type) =
if let Some(tup) = crate::ffmpeg::input_type_bytes(bytes.clone()).await? {
tup
} else {
crate::magick::input_type_bytes(bytes.clone()).await?
};
if !validate {
2021-10-23 17:35:07 +00:00
return Ok((input_type, Either::left(UnvalidatedBytes::new(bytes))));
}
2023-02-04 23:32:36 +00:00
match (input_type.to_file_format(), media.format) {
(FileFormat::Video(video_format), _) => {
2023-02-04 23:32:36 +00:00
if !(media.enable_silent_video || media.enable_full_video) {
2022-03-29 16:04:56 +00:00
return Err(UploadError::SilentVideoDisabled.into());
}
2023-02-04 23:32:36 +00:00
let transcode_options = TranscodeOptions::new(media, &details, video_format);
if transcode_options.needs_reencode() {
Ok((
transcode_options.output_type(),
Either::right(Either::left(Either::left(
crate::ffmpeg::transcode_bytes(bytes, transcode_options).await?,
))),
))
} else {
Ok((
transcode_options.output_type(),
Either::right(Either::right(crate::exiftool::clear_metadata_bytes_read(
bytes,
)?)),
))
}
}
(FileFormat::Image(image_format), Some(format)) if image_format != format => Ok((
ValidInputType::from_format(format),
Either::right(Either::left(Either::right(
crate::magick::convert_bytes_read(bytes, format)?,
2021-10-21 01:13:39 +00:00
))),
)),
(FileFormat::Image(ImageFormat::Webp), _) => Ok((
ValidInputType::Webp,
Either::right(Either::left(Either::right(
crate::magick::convert_bytes_read(bytes, ImageFormat::Webp)?,
))),
)),
2022-10-15 16:13:24 +00:00
(FileFormat::Image(image_format), _) => {
if crate::exiftool::needs_reorienting(bytes.clone()).await? {
Ok((
ValidInputType::from_format(image_format),
Either::right(Either::left(Either::right(
crate::magick::convert_bytes_read(bytes, image_format)?,
))),
))
} else {
Ok((
ValidInputType::from_format(image_format),
Either::right(Either::right(crate::exiftool::clear_metadata_bytes_read(
bytes,
)?)),
))
}
}
}
}