mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-12-22 11:21:24 +00:00
Version v0.3.0-alpha.13-shell-out-r3
This commit is contained in:
parent
fe66633802
commit
d4733321ed
4 changed files with 23 additions and 74 deletions
|
@ -2,7 +2,7 @@ version: '3.3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
pictrs:
|
pictrs:
|
||||||
image: asonix/pictrs:v0.3.0-alpha.13-shell-out-r2
|
image: asonix/pictrs:v0.3.0-alpha.13-shell-out-r3
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8080:8080"
|
- "127.0.0.1:8080:8080"
|
||||||
restart: always
|
restart: always
|
||||||
|
|
44
src/exiv2.rs
44
src/exiv2.rs
|
@ -19,14 +19,6 @@ pub(crate) enum Exvi2Error {
|
||||||
Unsupported,
|
Unsupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum ValidInputType {
|
|
||||||
Mp4,
|
|
||||||
Gif,
|
|
||||||
Png,
|
|
||||||
Jpeg,
|
|
||||||
Webp,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct Details {
|
pub(crate) struct Details {
|
||||||
pub(crate) mime_type: mime::Mime,
|
pub(crate) mime_type: mime::Mime,
|
||||||
pub(crate) width: usize,
|
pub(crate) width: usize,
|
||||||
|
@ -62,42 +54,6 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn input_type<P>(file: P) -> Result<ValidInputType, Exvi2Error>
|
|
||||||
where
|
|
||||||
P: AsRef<std::path::Path>,
|
|
||||||
{
|
|
||||||
let permit = semaphore().acquire().await?;
|
|
||||||
|
|
||||||
let output = tokio::process::Command::new("exiv2")
|
|
||||||
.arg(&"pr")
|
|
||||||
.arg(&file.as_ref())
|
|
||||||
.output()
|
|
||||||
.await?;
|
|
||||||
drop(permit);
|
|
||||||
|
|
||||||
let s = String::from_utf8_lossy(&output.stdout);
|
|
||||||
|
|
||||||
let mime_line = s
|
|
||||||
.lines()
|
|
||||||
.find(|line| line.starts_with("MIME"))
|
|
||||||
.ok_or_else(|| Exvi2Error::Missing)?;
|
|
||||||
|
|
||||||
let mut segments = mime_line.rsplit(':');
|
|
||||||
let mime_type = segments.next().ok_or_else(|| Exvi2Error::Missing)?;
|
|
||||||
|
|
||||||
let input_type = match mime_type.trim() {
|
|
||||||
"video/mp4" => ValidInputType::Mp4,
|
|
||||||
"video/quicktime" => ValidInputType::Mp4,
|
|
||||||
"image/gif" => ValidInputType::Gif,
|
|
||||||
"image/png" => ValidInputType::Png,
|
|
||||||
"image/jpeg" => ValidInputType::Jpeg,
|
|
||||||
"image/webp" => ValidInputType::Webp,
|
|
||||||
_ => return Err(Exvi2Error::Unsupported),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(input_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn details<P>(file: P) -> Result<Details, Exvi2Error>
|
pub(crate) async fn details<P>(file: P) -> Result<Details, Exvi2Error>
|
||||||
where
|
where
|
||||||
P: AsRef<std::path::Path>,
|
P: AsRef<std::path::Path>,
|
||||||
|
|
|
@ -13,22 +13,14 @@ pub(crate) enum MagickError {
|
||||||
Format,
|
Format,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum ValidFormat {
|
pub(crate) enum ValidInputType {
|
||||||
Jpeg,
|
Mp4,
|
||||||
|
Gif,
|
||||||
Png,
|
Png,
|
||||||
|
Jpeg,
|
||||||
Webp,
|
Webp,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidFormat {
|
|
||||||
fn as_magic_type(&self) -> &'static str {
|
|
||||||
match self {
|
|
||||||
ValidFormat::Jpeg => "JPEG",
|
|
||||||
ValidFormat::Png => "PNG",
|
|
||||||
ValidFormat::Webp => "WEBP",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static MAX_CONVERSIONS: once_cell::sync::OnceCell<tokio::sync::Semaphore> =
|
static MAX_CONVERSIONS: once_cell::sync::OnceCell<tokio::sync::Semaphore> =
|
||||||
once_cell::sync::OnceCell::new();
|
once_cell::sync::OnceCell::new();
|
||||||
|
|
||||||
|
@ -69,7 +61,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn validate_format<P>(file: &P, format: ValidFormat) -> Result<(), MagickError>
|
pub(crate) async fn input_type<P>(file: &P) -> Result<ValidInputType, MagickError>
|
||||||
where
|
where
|
||||||
P: AsRef<std::path::Path>,
|
P: AsRef<std::path::Path>,
|
||||||
{
|
{
|
||||||
|
@ -85,13 +77,22 @@ where
|
||||||
|
|
||||||
let s = String::from_utf8_lossy(&output.stdout);
|
let s = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
||||||
if s.lines()
|
let mut lines = s.lines();
|
||||||
.all(|item| item.is_empty() || item == format.as_magic_type())
|
let first = lines.next();
|
||||||
{
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(MagickError::Format)
|
let opt = lines.fold(first, |acc, item| match acc {
|
||||||
|
Some(prev) if prev == item => Some(prev),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
match opt {
|
||||||
|
Some("MP4") => Ok(ValidInputType::Mp4),
|
||||||
|
Some("GIF") => Ok(ValidInputType::Gif),
|
||||||
|
Some("PNG") => Ok(ValidInputType::Png),
|
||||||
|
Some("JPEG") => Ok(ValidInputType::Jpeg),
|
||||||
|
Some("WEBP") => Ok(ValidInputType::Webp),
|
||||||
|
_ => Err(MagickError::Format),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn process_image<P1, P2>(
|
pub(crate) async fn process_image<P1, P2>(
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use crate::{
|
use crate::{config::Format, error::UploadError, magick::ValidInputType, tmp_file};
|
||||||
config::Format, error::UploadError, exiv2::ValidInputType, magick::ValidFormat, tmp_file,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) fn image_webp() -> mime::Mime {
|
pub(crate) fn image_webp() -> mime::Mime {
|
||||||
"image/webp".parse().unwrap()
|
"image/webp".parse().unwrap()
|
||||||
|
@ -16,7 +14,7 @@ pub(crate) async fn validate_image(
|
||||||
tmpfile: std::path::PathBuf,
|
tmpfile: std::path::PathBuf,
|
||||||
prescribed_format: Option<Format>,
|
prescribed_format: Option<Format>,
|
||||||
) -> Result<mime::Mime, UploadError> {
|
) -> Result<mime::Mime, UploadError> {
|
||||||
let input_type = crate::exiv2::input_type(&tmpfile).await?;
|
let input_type = crate::magick::input_type(&tmpfile).await?;
|
||||||
|
|
||||||
match (prescribed_format, input_type) {
|
match (prescribed_format, input_type) {
|
||||||
(_, ValidInputType::Gif) | (_, ValidInputType::Mp4) => {
|
(_, ValidInputType::Gif) | (_, ValidInputType::Mp4) => {
|
||||||
|
@ -28,8 +26,6 @@ pub(crate) async fn validate_image(
|
||||||
Ok(video_mp4())
|
Ok(video_mp4())
|
||||||
}
|
}
|
||||||
(Some(Format::Jpeg), ValidInputType::Jpeg) | (None, ValidInputType::Jpeg) => {
|
(Some(Format::Jpeg), ValidInputType::Jpeg) | (None, ValidInputType::Jpeg) => {
|
||||||
tracing::debug!("Validating format");
|
|
||||||
crate::magick::validate_format(&tmpfile, ValidFormat::Jpeg).await?;
|
|
||||||
tracing::debug!("Clearing metadata");
|
tracing::debug!("Clearing metadata");
|
||||||
crate::exiv2::clear_metadata(&tmpfile).await?;
|
crate::exiv2::clear_metadata(&tmpfile).await?;
|
||||||
tracing::debug!("Validated");
|
tracing::debug!("Validated");
|
||||||
|
@ -37,8 +33,6 @@ pub(crate) async fn validate_image(
|
||||||
Ok(mime::IMAGE_JPEG)
|
Ok(mime::IMAGE_JPEG)
|
||||||
}
|
}
|
||||||
(Some(Format::Png), ValidInputType::Png) | (None, ValidInputType::Png) => {
|
(Some(Format::Png), ValidInputType::Png) | (None, ValidInputType::Png) => {
|
||||||
tracing::debug!("Validating format");
|
|
||||||
crate::magick::validate_format(&tmpfile, ValidFormat::Png).await?;
|
|
||||||
tracing::debug!("Clearing metadata");
|
tracing::debug!("Clearing metadata");
|
||||||
crate::exiv2::clear_metadata(&tmpfile).await?;
|
crate::exiv2::clear_metadata(&tmpfile).await?;
|
||||||
tracing::debug!("Validated");
|
tracing::debug!("Validated");
|
||||||
|
@ -46,8 +40,6 @@ pub(crate) async fn validate_image(
|
||||||
Ok(mime::IMAGE_PNG)
|
Ok(mime::IMAGE_PNG)
|
||||||
}
|
}
|
||||||
(Some(Format::Webp), ValidInputType::Webp) | (None, ValidInputType::Webp) => {
|
(Some(Format::Webp), ValidInputType::Webp) | (None, ValidInputType::Webp) => {
|
||||||
tracing::debug!("Validating format");
|
|
||||||
crate::magick::validate_format(&tmpfile, ValidFormat::Webp).await?;
|
|
||||||
tracing::debug!("Clearing metadata");
|
tracing::debug!("Clearing metadata");
|
||||||
crate::exiv2::clear_metadata(&tmpfile).await?;
|
crate::exiv2::clear_metadata(&tmpfile).await?;
|
||||||
tracing::debug!("Validated");
|
tracing::debug!("Validated");
|
||||||
|
|
Loading…
Reference in a new issue