[librsvg: 3/6] xml: append stylesheets to the builder and then load them



commit 566104088cb6def72864583856d051e6b4e28511
Author: Paolo Borelli <pborelli gnome org>
Date:   Fri Nov 1 18:37:35 2019 +0100

    xml: append stylesheets to the builder and then load them
    
    Instead of loading them as we find them, push stylesheet in a vec
    and then load them in one go. This makes error handling easier
    and also moves the svg specific logic (which stylesheets are
    supported) from xml to document.

 rsvg_internals/src/document.rs | 40 +++++++++++++++++++++++++++++++++++-----
 rsvg_internals/src/error.rs    |  3 +++
 rsvg_internals/src/xml.rs      | 22 ++++++----------------
 3 files changed, 44 insertions(+), 21 deletions(-)
---
diff --git a/rsvg_internals/src/document.rs b/rsvg_internals/src/document.rs
index a08ba83d..8d82de1a 100644
--- a/rsvg_internals/src/document.rs
+++ b/rsvg_internals/src/document.rs
@@ -207,10 +207,17 @@ fn load_image(
     Ok(surface)
 }
 
+struct Stylesheet {
+    alternate: Option<String>,
+    type_: Option<String>,
+    href: Option<String>,
+}
+
 pub struct DocumentBuilder {
     load_options: LoadOptions,
     tree: Option<RsvgNode>,
     ids: HashMap<String, RsvgNode>,
+    stylesheets: Vec<Stylesheet>,
     css_rules: CssRules,
 }
 
@@ -220,10 +227,24 @@ impl DocumentBuilder {
             load_options: load_options.clone(),
             tree: None,
             ids: HashMap::new(),
+            stylesheets: Vec::new(),
             css_rules: CssRules::default(),
         }
     }
 
+    pub fn append_stylesheet(
+        &mut self,
+        alternate: Option<String>,
+        type_: Option<String>,
+        href: Option<String>,
+    ) {
+        self.stylesheets.push(Stylesheet {
+            alternate,
+            type_,
+            href,
+        });
+    }
+
     pub fn append_element(
         &mut self,
         name: &QualName,
@@ -291,17 +312,26 @@ impl DocumentBuilder {
             .map_err(|_| LoadingError::BadUrl)
     }
 
-    pub fn load_css(&mut self, url: &AllowedUrl) {
-        // FIXME: handle CSS errors
-        let _ = self.css_rules.load_css(&url);
-    }
-
     pub fn parse_css(&mut self, css_data: &str) {
         self.css_rules
             .parse(self.load_options.base_url.as_ref(), css_data);
     }
 
     pub fn build(mut self) -> Result<Document, LoadingError> {
+        for s in self.stylesheets.iter() {
+            if s.type_.as_ref().map(String::as_str) != Some("text/css")
+                || (s.alternate.is_some() && s.alternate.as_ref().map(String::as_str) != Some("no"))
+                || s.href.is_none()
+            {
+                return Err(LoadingError::BadStylesheet);
+            }
+
+            // FIXME: handle CSS errors
+            let _ = self
+                .css_rules
+                .load_css(&self.resolve_href(s.href.as_ref().unwrap())?);
+        }
+
         match self.tree {
             None => Err(LoadingError::SvgHasNoElements),
             Some(ref mut root) if root.borrow().get_type() == NodeType::Svg => {
diff --git a/rsvg_internals/src/error.rs b/rsvg_internals/src/error.rs
index ee84801a..2ae9878d 100644
--- a/rsvg_internals/src/error.rs
+++ b/rsvg_internals/src/error.rs
@@ -221,6 +221,7 @@ pub enum LoadingError {
     CouldNotCreateXmlParser,
     BadUrl,
     BadDataUrl,
+    BadStylesheet,
     BadCss,
     Cairo(cairo::Status),
     EmptyData,
@@ -238,6 +239,7 @@ impl error::Error for LoadingError {
             LoadingError::XmlParseError(_) => "XML parse error",
             LoadingError::BadUrl => "invalid URL",
             LoadingError::BadDataUrl => "invalid data: URL",
+            LoadingError::BadStylesheet => "invalid stylesheet",
             LoadingError::BadCss => "invalid CSS",
             LoadingError::Cairo(_) => "cairo error",
             LoadingError::EmptyData => "empty data",
@@ -258,6 +260,7 @@ impl fmt::Display for LoadingError {
             | LoadingError::CouldNotCreateXmlParser
             | LoadingError::BadUrl
             | LoadingError::BadDataUrl
+            | LoadingError::BadStylesheet
             | LoadingError::BadCss
             | LoadingError::EmptyData
             | LoadingError::SvgHasNoElements
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index f1b1bfb5..83643e06 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -230,22 +230,12 @@ impl XmlState {
                 }
             }
 
-            if (alternate == None || alternate.as_ref().map(String::as_str) == Some("no"))
-                && type_.as_ref().map(String::as_str) == Some("text/css")
-                && href.is_some()
-            {
-                let mut inner = self.inner.borrow_mut();
-                let href = href.as_ref().unwrap();
-
-                if let Ok(aurl) = inner.document_builder.as_ref().unwrap().resolve_href(href) {
-                    inner.document_builder.as_mut().unwrap().load_css(&aurl);
-                } else {
-                    self.error(ParseFromStreamError::XmlParseError(format!(
-                        "disallowed URL '{}' in xml-stylesheet",
-                        href
-                    )));
-                }
-            }
+            let mut inner = self.inner.borrow_mut();
+            inner
+                .document_builder
+                .as_mut()
+                .unwrap()
+                .append_stylesheet(alternate, type_, href);
         } else {
             self.error(ParseFromStreamError::XmlParseError(String::from(
                 "invalid processing instruction data in xml-stylesheet",


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