[librsvg] Handle: move the base_url here
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] Handle: move the base_url here
- Date: Tue, 27 Nov 2018 00:24:07 +0000 (UTC)
commit 56f787b311b027c340bc3de4494bd6a3b09e2fb6
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Nov 26 13:34:52 2018 -0600
Handle: move the base_url here
We keep it as a RefCell<Option<Url>> for the following reasons:
- Url, from the url crate, because it does validation and will let us
resolve relative hrefs later.
- Option, because the base_url may not be set at all.
- RefCell - interior mutability; the handle allows setting this after
creation.
librsvg/rsvg-handle.c | 42 +++++++++++++++++++---------
librsvg/rsvg-private.h | 12 ++++++--
rsvg_internals/src/font_props.rs | 3 +-
rsvg_internals/src/handle.rs | 60 ++++++++++++++++++++++++++++++++++++----
rsvg_internals/src/lib.rs | 8 +++++-
tests/api.c | 40 +++++++++++++++++++++++++++
6 files changed, 142 insertions(+), 23 deletions(-)
---
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index eab2d59b..1241e7e3 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -192,7 +192,6 @@ rsvg_handle_dispose (GObject *instance)
g_clear_pointer (&self->priv->css_styles, rsvg_css_styles_free);
g_clear_pointer (&self->priv->tree, rsvg_tree_free);
g_clear_pointer (&self->priv->base_uri, g_free);
- g_clear_object (&self->priv->base_gfile);
#ifdef HAVE_PANGOFT2
g_clear_pointer (&self->priv->font_config_for_testing, FcConfigDestroy);
@@ -899,19 +898,28 @@ rsvg_handle_set_base_gfile (RsvgHandle *handle,
GFile *base_file)
{
RsvgHandlePrivate *priv;
+ char *uri;
+ GFile *real_base_file;
g_return_if_fail (RSVG_IS_HANDLE (handle));
g_return_if_fail (G_IS_FILE (base_file));
priv = handle->priv;
- g_object_ref (base_file);
- if (priv->base_gfile)
- g_object_unref (priv->base_gfile);
- priv->base_gfile = base_file;
+ uri = g_file_get_uri (base_file);
+ rsvg_handle_rust_set_base_url (priv->rust_handle, uri);
+ g_free (uri);
+
+ /* Obtain the sanitized version */
+ real_base_file = rsvg_handle_rust_get_base_gfile (priv->rust_handle);
g_free (priv->base_uri);
- priv->base_uri = g_file_get_uri (base_file);
+
+ if (real_base_file) {
+ priv->base_uri = g_file_get_uri (real_base_file);
+ } else {
+ priv->base_uri = NULL;
+ }
}
/**
@@ -1538,15 +1546,19 @@ rsvg_handle_resolve_uri (RsvgHandle *handle,
{
RsvgHandlePrivate *priv = handle->priv;
char *scheme, *resolved_uri;
+ GFile *base_gfile;
GFile *base, *resolved;
if (uri == NULL)
return NULL;
+ base_gfile = rsvg_handle_rust_get_base_gfile (priv->rust_handle);
+
scheme = g_uri_parse_scheme (uri);
if (scheme != NULL ||
- priv->base_gfile == NULL ||
- (base = g_file_get_parent (priv->base_gfile)) == NULL) {
+ base_gfile == NULL ||
+ (base = g_file_get_parent (base_gfile)) == NULL) {
+ g_object_unref (base_gfile);
g_free (scheme);
return g_strdup (uri);
}
@@ -1556,6 +1568,7 @@ rsvg_handle_resolve_uri (RsvgHandle *handle,
g_free (scheme);
g_object_unref (base);
+ g_object_unref (base_gfile);
g_object_unref (resolved);
return resolved_uri;
@@ -1591,14 +1604,17 @@ rsvg_realpath_utf8 (const char *filename, const char *unused)
#endif
static gboolean
-allow_load (GFile *base_gfile, const char *uri, GError **error)
+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 */
@@ -1655,12 +1671,14 @@ allow_load (GFile *base_gfile, const char *uri, GError **error)
/* 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);
@@ -1685,13 +1703,12 @@ _rsvg_handle_acquire_data (RsvgHandle *handle,
gsize *len,
GError **error)
{
- RsvgHandlePrivate *priv = handle->priv;
char *uri;
char *data;
uri = rsvg_handle_resolve_uri (handle, href);
- if (allow_load (priv->base_gfile, uri, error)) {
+ if (allow_load (handle, uri, error)) {
data = rsvg_io_acquire_data (uri,
content_type,
len,
@@ -1716,13 +1733,12 @@ _rsvg_handle_acquire_stream (RsvgHandle *handle,
const char *href,
GError **error)
{
- RsvgHandlePrivate *priv = handle->priv;
char *uri;
GInputStream *stream;
uri = rsvg_handle_resolve_uri (handle, href);
- if (allow_load (priv->base_gfile, uri, error)) {
+ if (allow_load (handle, uri, error)) {
stream = rsvg_io_acquire_stream (uri, handle->priv->cancellable, error);
} else {
stream = NULL;
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index b79e3f53..f9a5b337 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -110,8 +110,7 @@ struct RsvgHandlePrivate {
double dpi_x;
double dpi_y;
- gchar *base_uri;
- GFile *base_gfile;
+ gchar *base_uri; // Keep this here; since rsvg_handle_get_base_uri() returns a const char *
gboolean in_loop; /* see get_dimension() */
@@ -272,6 +271,15 @@ RsvgHandleRust *rsvg_handle_rust_new (void);
G_GNUC_INTERNAL
void rsvg_handle_rust_free (RsvgHandleRust *raw_handle);
+/* Implemented in rsvg_internals/src/handle.rs */
+G_GNUC_INTERNAL
+void rsvg_handle_rust_set_base_url (RsvgHandleRust *raw_handle,
+ const char *uri);
+
+/* Implemented in rsvg_internals/src/handle.rs */
+G_GNUC_INTERNAL
+GFile *rsvg_handle_rust_get_base_gfile (RsvgHandleRust *raw_handle);
+
G_GNUC_INTERNAL
RsvgHandle *rsvg_handle_load_extern (RsvgHandle *handle,
const char *uri);
diff --git a/rsvg_internals/src/font_props.rs b/rsvg_internals/src/font_props.rs
index 317bd83b..936937b6 100644
--- a/rsvg_internals/src/font_props.rs
+++ b/rsvg_internals/src/font_props.rs
@@ -169,8 +169,7 @@ impl Parse for FontWeightSpec {
800 => Ok(FontWeightSpec::W800),
900 => Ok(FontWeightSpec::W900),
_ => Err(()),
- })
- {
+ }) {
Ok(r)
} else {
Err(ValueErrorKind::Parse(ParseError::new(
diff --git a/rsvg_internals/src/handle.rs b/rsvg_internals/src/handle.rs
index ed53bc79..720dee56 100644
--- a/rsvg_internals/src/handle.rs
+++ b/rsvg_internals/src/handle.rs
@@ -1,14 +1,16 @@
+use std::cell::RefCell;
use std::ptr;
use cairo::{ImageSurface, Status};
use cairo_sys;
use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
-use gio::InputStream;
+use gio::{File as GFile, InputStream};
use gio_sys;
use glib;
use glib::translate::*;
use glib_sys;
use libc;
+use url::Url;
use css::{self, CssStyles, RsvgCssStyles};
use defs::{Defs, RsvgDefs};
@@ -20,7 +22,17 @@ pub enum RsvgHandle {}
pub enum RsvgHandleRust {}
-struct Handle {}
+struct Handle {
+ base_url: RefCell<Option<Url>>,
+}
+
+impl Handle {
+ fn new() -> Handle {
+ Handle {
+ base_url: RefCell::new(None),
+ }
+ }
+}
#[allow(improper_ctypes)]
extern "C" {
@@ -252,7 +264,7 @@ pub unsafe extern "C" fn rsvg_handle_load_css(handle: *mut RsvgHandle, href: *co
#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_new() -> *mut RsvgHandleRust {
- Box::into_raw(Box::new(Handle {})) as *mut RsvgHandleRust
+ Box::into_raw(Box::new(Handle::new())) as *mut RsvgHandleRust
}
#[no_mangle]
@@ -263,7 +275,45 @@ pub unsafe extern "C" fn rsvg_handle_rust_free(raw_handle: *mut RsvgHandleRust)
}
fn get_rust_handle(handle: *const RsvgHandle) -> *mut Handle {
- unsafe {
- rsvg_handle_get_rust(handle) as *mut Handle
+ unsafe { rsvg_handle_get_rust(handle) as *mut Handle }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_set_base_url(
+ raw_handle: *const RsvgHandleRust,
+ uri: *const libc::c_char,
+) {
+ let handle = &*(raw_handle as *const Handle);
+
+ assert!(!uri.is_null());
+ let uri: String = from_glib_none(uri);
+
+ let url = match Url::parse(&uri) {
+ Ok(u) => u,
+
+ Err(e) => {
+ rsvg_log!(
+ "not setting base_uri to \"{}\" since it is invalid: {}",
+ uri,
+ e
+ );
+ return;
+ }
+ };
+
+ rsvg_log!("setting base_uri to \"{}\"", url);
+ *handle.base_url.borrow_mut() = Some(url);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_handle_rust_get_base_gfile(
+ raw_handle: *const RsvgHandleRust,
+) -> *mut gio_sys::GFile {
+ let handle = &*(raw_handle as *const Handle);
+
+ match *handle.base_url.borrow() {
+ None => ptr::null_mut(),
+
+ Some(ref url) => GFile::new_for_uri(url.as_str()).to_glib_full(),
}
}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 56a80575..6ad88a6b 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -46,7 +46,13 @@ pub use drawing_ctx::{
rsvg_drawing_ctx_new,
};
-pub use handle::{rsvg_handle_load_css, rsvg_handle_rust_free, rsvg_handle_rust_new};
+pub use handle::{
+ rsvg_handle_load_css,
+ rsvg_handle_rust_free,
+ rsvg_handle_rust_get_base_gfile,
+ rsvg_handle_rust_new,
+ rsvg_handle_rust_set_base_url,
+};
pub use io::{
rsvg_decode_data_uri,
diff --git a/tests/api.c b/tests/api.c
index 9ea3ae97..75d3883c 100644
--- a/tests/api.c
+++ b/tests/api.c
@@ -228,6 +228,44 @@ auto_generated (void)
g_assert_cmpstr (q.type_name, ==, "RsvgHandleFlags");
}
+static void
+base_uri (void)
+{
+ RsvgHandle *handle = rsvg_handle_new ();
+ const char *uri;
+
+ uri = rsvg_handle_get_base_uri (handle);
+ g_assert (uri == NULL);
+
+ rsvg_handle_set_base_uri (handle, "file:///foo/bar.svg");
+ uri = rsvg_handle_get_base_uri (handle);
+
+ g_assert_cmpstr (uri, ==, "file:///foo/bar.svg");
+
+ g_object_unref (handle);
+}
+
+static void
+base_gfile (void)
+{
+ RsvgHandle *handle = rsvg_handle_new ();
+ GFile *file;
+ const char *uri;
+
+ uri = rsvg_handle_get_base_uri (handle);
+ g_assert (uri == NULL);
+
+ file = g_file_new_for_uri ("file:///foo/bar.svg");
+
+ rsvg_handle_set_base_gfile (handle, file);
+ uri = rsvg_handle_get_base_uri (handle);
+
+ g_assert_cmpstr (uri, ==, "file:///foo/bar.svg");
+
+ g_object_unref (file);
+ g_object_unref (handle);
+}
+
static void
handle_write_close_free (void)
{
@@ -594,6 +632,8 @@ main (int argc, char **argv)
g_test_add_func ("/api/set_dpi", set_dpi);
g_test_add_func ("/api/error_quark", error_quark);
g_test_add_func ("/api/auto_generated", auto_generated);
+ g_test_add_func ("/api/base_uri", base_uri);
+ g_test_add_func ("/api/base_gfile", base_gfile);
g_test_add_func ("/api/handle_write_close_free", handle_write_close_free);
g_test_add_func ("/api/handle_new_from_file", handle_new_from_file);
g_test_add_func ("/api/handle_new_from_data", handle_new_from_data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]