[librsvg] rsvg_handle_acquire_stream(): Move to Rust



commit 87622ba01abf46aae07139d0574edf101a557728
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Nov 26 17:41:36 2018 -0600

    rsvg_handle_acquire_stream(): Move to Rust
    
    This completely moves allow_load() and the realpath() machinery to
    Rust.  Yay!

 librsvg/rsvg-handle.c        | 142 +------------------------------------------
 librsvg/rsvg-load.c          |   2 +-
 librsvg/rsvg-private.h       |   9 +--
 rsvg_internals/src/handle.rs |  40 +++++++++---
 rsvg_internals/src/io.rs     |  35 +++--------
 rsvg_internals/src/lib.rs    |   3 +-
 6 files changed, 48 insertions(+), 183 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index b10fec49..ec6bbc51 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -1016,7 +1016,7 @@ rsvg_handle_load_extern (RsvgHandle *handle, const char *uri)
     RsvgHandle *res = NULL;
     GInputStream *stream;
 
-    stream = _rsvg_handle_acquire_stream (handle, uri, NULL);
+    stream = rsvg_handle_acquire_stream (handle, uri, NULL);
 
     if (stream) {
         GFile *file = g_file_new_for_uri (uri);
@@ -1578,152 +1578,12 @@ rsvg_handle_resolve_uri (RsvgHandle *handle,
     return resolved_uri;
 }
 
-#ifdef G_OS_WIN32
-static char *
-rsvg_realpath_utf8 (const char *filename, const char *unused)
-{
-    wchar_t *wfilename;
-    wchar_t *wfull;
-    char *full;
-
-    wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-    if (!wfilename)
-        return NULL;
-
-    wfull = _wfullpath (NULL, wfilename, 0);
-    g_free (wfilename);
-    if (!wfull)
-        return NULL;
-
-    full = g_utf16_to_utf8 (wfull, -1, NULL, NULL, NULL);
-    free (wfull);
-
-    if (!full)
-        return NULL;
-
-    return full;
-}
-
-#define realpath(a,b) rsvg_realpath_utf8 (a, b)
-#endif
-
-static gboolean
-allow_load (RsvgHandle *handle, const char *uri, GError **error)
-{
-    GFile *base_gfile;
-    GFile *base;
-    char *path, *dir;
-    char *scheme = NULL, *cpath = NULL, *cdir = NULL;
-
-    g_assert (error == NULL || *error == NULL);
-
-    base_gfile = rsvg_handle_rust_get_base_gfile (handle->priv->rust_handle);
-
-    scheme = g_uri_parse_scheme (uri);
-
-    /* Not a valid URI */
-    if (scheme == NULL)
-        goto deny;
-
-    /* Allow loads of data: from any location */
-    if (g_str_equal (scheme, "data"))
-        goto allow;
-
-    /* No base to compare to? */
-    if (base_gfile == NULL)
-        goto deny;
-
-    /* Deny loads from differing URI schemes */
-    if (!g_file_has_uri_scheme (base_gfile, scheme))
-        goto deny;
-
-    /* resource: is allowed to load anything from other resources */
-    if (g_str_equal (scheme, "resource"))
-        goto allow;
-
-    /* Non-file: isn't allowed to load anything */
-    if (!g_str_equal (scheme, "file"))
-        goto deny;
-
-    base = g_file_get_parent (base_gfile);
-    if (base == NULL)
-        goto deny;
-
-    dir = g_file_get_path (base);
-    g_object_unref (base);
-
-    cdir = realpath (dir, NULL);
-    g_free (dir);
-    if (cdir == NULL)
-        goto deny;
-
-    path = g_filename_from_uri (uri, NULL, NULL);
-    if (path == NULL)
-        goto deny;
-
-    cpath = realpath (path, NULL);
-    g_free (path);
-
-    if (cpath == NULL)
-        goto deny;
-
-    /* Now check that @cpath is below @cdir */
-    if (!g_str_has_prefix (cpath, cdir) ||
-        cpath[strlen (cdir)] != G_DIR_SEPARATOR)
-        goto deny;
-
-    /* Allow load! */
-
- allow:
-    g_object_unref (base_gfile);
-    g_free (scheme);
-    free (cpath);
-    free (cdir);
-    return TRUE;
-
- deny:
-    g_object_unref (base_gfile);
-    g_free (scheme);
-    free (cpath);
-    free (cdir);
-
-    g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
-                 "File may not link to URI \"%s\"", uri);
-    return FALSE;
-}
-
 GCancellable *
 rsvg_handle_get_cancellable (RsvgHandle *handle)
 {
     return handle->priv->cancellable;
 }
 
-/* Implemented in rsvg_internals/src/io.rs */
-G_GNUC_INTERNAL
-GInputStream *rsvg_io_acquire_stream (const char *uri,
-                                     GCancellable *cancellable,
-                                     GError **error);
-
-GInputStream *
-_rsvg_handle_acquire_stream (RsvgHandle *handle,
-                             const char *href,
-                             GError **error)
-{
-    char *uri;
-    GInputStream *stream;
-
-    uri = rsvg_handle_resolve_uri (handle, href);
-
-    if (allow_load (handle, uri, error)) {
-        stream = rsvg_io_acquire_stream (uri, handle->priv->cancellable, error);
-    } else {
-        stream = NULL;
-    }
-
-    g_free (uri);
-    return stream;
-}
-
 #ifdef HAVE_PANGOFT2
 
 static void
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index 85f057f6..caf5678d 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -276,7 +276,7 @@ rsvg_load_handle_xml_xinclude (RsvgHandle *handle, const char *href)
 
     g_assert (handle->priv->load != NULL);
 
-    stream = _rsvg_handle_acquire_stream (handle, href, NULL);
+    stream = rsvg_handle_acquire_stream (handle, href, NULL);
 
     if (stream) {
         gboolean success = FALSE;
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index 11b42403..d612dfcc 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -297,12 +297,13 @@ char *rsvg_handle_acquire_data (RsvgHandle *handle,
 G_GNUC_INTERNAL
 GCancellable *rsvg_handle_get_cancellable (RsvgHandle *handle);
 
+/* Implemented in rsvg_internals/src/handle.rs */
 G_GNUC_INTERNAL
-GInputStream *_rsvg_handle_acquire_stream (RsvgHandle *handle,
-                                           const char *href,
-                                           GError **error);
+GInputStream *rsvg_handle_acquire_stream (RsvgHandle *handle,
+                                          const char *href,
+                                          GError **error);
 
-#define rsvg_return_if_fail(expr, error)    G_STMT_START{                      \
+#define rsvg_return_if_fail(expr, error)    G_STMT_START{           \
      if G_LIKELY(expr) { } else                                     \
        {                                                            \
            rsvg_return_if_fail_warning (G_STRFUNC,                  \
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index d26891ef..e3a62c00 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -128,17 +128,13 @@ pub fn acquire_data(handle: *mut RsvgHandle, href: &str) -> Result<BinaryData, g
 }
 
 pub fn acquire_stream(handle: *mut RsvgHandle, href: &str) -> Result<InputStream, glib::Error> {
-    unsafe {
-        let mut error = ptr::null_mut();
+    let rhandle = get_rust_handle(handle);
 
-        let stream = _rsvg_handle_acquire_stream(handle, href.to_glib_none().0, &mut error);
+    let aurl = AllowedUrl::from_href(href, rhandle.base_url.borrow().as_ref())
+        .map_err(|_| glib::Error::new(RsvgError, "FIXME"))?;
 
-        if stream.is_null() {
-            Err(from_glib_full(error))
-        } else {
-            Ok(from_glib_full(stream))
-        }
-    }
+    io::acquire_stream(&aurl, get_cancellable(handle).as_ref())
+        .map_err(|_| glib::Error::new(RsvgError, "FIXME"))
 }
 
 fn keep_image_data(handle: *const RsvgHandle) -> bool {
@@ -333,3 +329,29 @@ pub unsafe extern "C" fn rsvg_handle_acquire_data(
         }
     }
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_acquire_stream(
+    handle: *mut RsvgHandle,
+    href: *const libc::c_char,
+    error: *mut *mut glib_sys::GError,
+) -> *mut gio_sys::GInputStream {
+    assert!(!href.is_null());
+
+    let href: String = from_glib_none(href);
+
+    match acquire_stream(handle, &href) {
+        Ok(stream) => {
+            if !error.is_null() {
+                *error = ptr::null_mut();
+            }
+
+            stream.to_glib_full()
+        }
+
+        Err(_) => {
+            set_gerror(error, 0, "Could not acquire stream");
+            ptr::null_mut()
+        }
+    }
+}
diff --git a/rsvg_internals/src/io.rs b/rsvg_internals/src/io.rs
index 4ac24ce1..905a326d 100644
--- a/rsvg_internals/src/io.rs
+++ b/rsvg_internals/src/io.rs
@@ -150,11 +150,13 @@ pub unsafe fn rsvg_get_input_stream_for_loading(
     }
 }
 
-/// Returns an input stream.  The uri can be a data: URL or a plain URI
-fn acquire_stream(
-    uri: &str,
-    cancellable: Option<Cancellable>,
+/// Returns an input stream.  The url can be a data: URL or a plain URI
+pub fn acquire_stream(
+    aurl: &AllowedUrl,
+    cancellable: Option<&Cancellable>,
 ) -> Result<InputStream, LoadingError> {
+    let uri = aurl.url().as_str();
+
     if uri.starts_with("data:") {
         let BinaryData { data, .. } = decode_data_uri(uri)?;
 
@@ -162,34 +164,13 @@ fn acquire_stream(
         Ok(stream.upcast::<InputStream>())
     } else {
         let file = GFile::new_for_uri(uri);
-        let stream = file.read(cancellable.as_ref())?;
+        let stream = file.read(cancellable)?;
 
         Ok(stream.upcast::<InputStream>())
     }
 }
 
-#[no_mangle]
-pub unsafe fn rsvg_io_acquire_stream(
-    uri: *const libc::c_char,
-    cancellable: *mut gio_sys::GCancellable,
-    error: *mut *mut glib_sys::GError,
-) -> *mut gio_sys::GInputStream {
-    assert!(!uri.is_null());
-
-    let uri: String = from_glib_none(uri);
-    let cancellable = from_glib_borrow(cancellable);
-
-    match acquire_stream(&uri, cancellable) {
-        Ok(stream) => stream.to_glib_full(),
-
-        Err(_e) => {
-            set_gerror(error, 0, "Could not acquire stream");
-
-            ptr::null_mut()
-        }
-    }
-}
-
+/// Returns a chunk of data.  The url can be a data: URL or a plain URI
 pub fn acquire_data(
     aurl: &AllowedUrl,
     cancellable: Option<&Cancellable>,
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index d0eafd58..fe5850c0 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -48,6 +48,7 @@ pub use drawing_ctx::{
 
 pub use handle::{
     rsvg_handle_acquire_data,
+    rsvg_handle_acquire_stream,
     rsvg_handle_load_css,
     rsvg_handle_rust_free,
     rsvg_handle_rust_get_base_gfile,
@@ -55,7 +56,7 @@ pub use handle::{
     rsvg_handle_rust_set_base_url,
 };
 
-pub use io::{rsvg_decode_data_uri, rsvg_get_input_stream_for_loading, rsvg_io_acquire_stream};
+pub use io::{rsvg_decode_data_uri, rsvg_get_input_stream_for_loading};
 
 pub use node::rsvg_node_unref;
 


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