[librsvg/librsvg-2.50] Use data_url::mime::Mime instead of a String in BinaryData.mime_type



commit 2996994d6b837ceb68bd88f3f0d6675df3ed03a2
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Mar 17 12:55:15 2021 -0600

    Use data_url::mime::Mime instead of a String in BinaryData.mime_type
    
    Types are good [citation needed].

 rsvg_internals/src/css.rs      |  9 +++++++--
 rsvg_internals/src/document.rs | 14 ++++++++++----
 rsvg_internals/src/io.rs       | 29 +++++++++++++++++++++++------
 3 files changed, 40 insertions(+), 12 deletions(-)
---
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index 0bb698ad..bc15cf5b 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -78,6 +78,7 @@ use cssparser::{
     CowRcStr, DeclarationListParser, DeclarationParser, Parser, ParserInput, QualifiedRuleParser,
     RuleListParser, SourceLocation, ToCss, _cssparser_internal_to_lowercase,
 };
+use data_url::mime::Mime;
 use markup5ever::{namespace_url, ns, LocalName, Namespace, Prefix, QualName};
 use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
 use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode, QuirksMode};
@@ -694,10 +695,10 @@ impl Stylesheet {
             .and_then(|data| {
                 let BinaryData {
                     data: bytes,
-                    content_type,
+                    mime_type,
                 } = data;
 
-                if content_type.as_ref().map(String::as_ref) == Some("text/css") {
+                if is_text_css(&mime_type) {
                     Ok(bytes)
                 } else {
                     rsvg_log!("\"{}\" is not of type text/css; ignoring", aurl);
@@ -749,6 +750,10 @@ impl Stylesheet {
     }
 }
 
+fn is_text_css(mime_type: &Mime) -> bool {
+    mime_type.type_ == "text" && mime_type.subtype == "css"
+}
+
 /// Runs the CSS cascade on the specified tree from all the stylesheets
 pub fn cascade(
     root: &mut Node,
diff --git a/rsvg_internals/src/document.rs b/rsvg_internals/src/document.rs
index 1675f2ce..b6008501 100644
--- a/rsvg_internals/src/document.rs
+++ b/rsvg_internals/src/document.rs
@@ -1,5 +1,6 @@
 //! Main SVG document structure.
 
+use data_url::mime::Mime;
 use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
 use markup5ever::QualName;
 use once_cell::sync::Lazy;
@@ -8,6 +9,7 @@ use std::collections::hash_map::Entry;
 use std::collections::HashMap;
 use std::include_str;
 use std::rc::Rc;
+use std::str::FromStr;
 
 use crate::allowed_url::{AllowedUrl, AllowedUrlError, Fragment};
 use crate::attributes::Attributes;
@@ -194,7 +196,7 @@ fn load_image(
 ) -> Result<SharedImageSurface, LoadingError> {
     let BinaryData {
         data: bytes,
-        mut content_type,
+        mime_type,
     } = io::acquire_data(&aurl, None)?;
 
     if bytes.is_empty() {
@@ -206,9 +208,13 @@ fn load_image(
     // Adobe Illustrator generate data: URLs without MIME-type for image
     // data.  We'll catch this and fall back to sniffing by unsetting the
     // content_type.
-    if content_type.as_deref() == Some("text/plain;charset=US-ASCII") {
-        content_type = None;
-    }
+    let unspecified_mime_type = Mime::from_str("text/plain;charset=US-ASCII").unwrap();
+
+    let content_type = if mime_type == unspecified_mime_type {
+        None
+    } else {
+        Some(format!("{}/{}", mime_type.type_, mime_type.subtype))
+    };
 
     let loader = if let Some(ref content_type) = content_type {
         PixbufLoader::new_with_mime_type(content_type)?
diff --git a/rsvg_internals/src/io.rs b/rsvg_internals/src/io.rs
index c884ef19..8b23aa2b 100644
--- a/rsvg_internals/src/io.rs
+++ b/rsvg_internals/src/io.rs
@@ -1,23 +1,33 @@
 //! Utilities to acquire streams and data from from URLs.
 
+use data_url::{mime::Mime, DataUrl};
 use gio::{
     BufferedInputStream, BufferedInputStreamExt, Cancellable, ConverterInputStream, File as GFile,
     FileExt, InputStream, MemoryInputStream, ZlibCompressorFormat, ZlibDecompressor,
 };
 use glib::{Bytes as GBytes, Cast};
+use std::str::FromStr;
 
 use crate::allowed_url::AllowedUrl;
 use crate::error::LoadingError;
 
 pub struct BinaryData {
     pub data: Vec<u8>,
-    pub content_type: Option<String>,
+    pub mime_type: Mime,
 }
 
 fn decode_data_uri(uri: &str) -> Result<BinaryData, LoadingError> {
-    let data_url = data_url::DataUrl::process(uri).map_err(|_| LoadingError::BadDataUrl)?;
+    let data_url = DataUrl::process(uri).map_err(|_| LoadingError::BadDataUrl)?;
 
-    let mime_type = data_url.mime_type().to_string();
+    let mime = data_url.mime_type();
+
+    // data_url::mime::Mime doesn't impl Clone, so do it by hand
+
+    let mime_type = Mime {
+        type_: mime.type_.clone(),
+        subtype: mime.subtype.clone(),
+        parameters: mime.parameters.clone(),
+    };
 
     let (bytes, fragment_id) = data_url
         .decode_to_vec()
@@ -34,7 +44,7 @@ fn decode_data_uri(uri: &str) -> Result<BinaryData, LoadingError> {
 
     Ok(BinaryData {
         data: bytes,
-        content_type: Some(mime_type),
+        mime_type,
     })
 }
 
@@ -110,11 +120,18 @@ pub fn acquire_data(
         let (contents, _etag) = file.load_contents(cancellable)?;
 
         let (content_type, _uncertain) = gio::content_type_guess(Some(uri), &contents);
-        let mime_type = gio::content_type_get_mime_type(&content_type).map(String::from);
+
+        let mime_type = if let Some(mime_type_str) = gio::content_type_get_mime_type(&content_type)
+        {
+            Mime::from_str(&mime_type_str)
+                .expect("gio::content_type_get_mime_type returned an invalid MIME-type!?")
+        } else {
+            Mime::from_str("application/octet-stream").unwrap()
+        };
 
         Ok(BinaryData {
             data: contents,
-            content_type: mime_type.map(From::from),
+            mime_type,
         })
     }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]