[0.11] gstreamer: uri: add gst_filename_to_uri() that takes relative filenames

Wim Taymans wtay at kemper.freedesktop.org
Fri Mar 4 07:18:48 PST 2011


Module: gstreamer
Branch: 0.11
Commit: 27027a2dd2c57d088e2a8b8d71c7526cf8083787
URL:    http://cgit.freedesktop.org/gstreamer/gstreamer/commit/?id=27027a2dd2c57d088e2a8b8d71c7526cf8083787

Author: Tim-Philipp Müller <tim.muller at collabora.co.uk>
Date:   Thu Feb 24 15:18:43 2011 +0000

uri: add gst_filename_to_uri() that takes relative filenames

Add function that (unlike the GLib equivalent) also accepts paths that
aren't absolute and will clean up relative markers such as ./ and ../
before forming a URI.

Fixes warnings with e.g. filesrc location=foo ! typefind caused by the
recent switch to g_filename_to_uri(), but also actually creates valid
URIs for the first time.

Windows code paths could need some more work, e.g. we don't clean up
the relative markers there for now (because path could have \ and /
as separators).

API: gst_filename_to_uri()

---

 docs/gst/gstreamer-sections.txt |    1 +
 gst/gsturi.c                    |  111 +++++++++++++++++++++++++++++++++++++++
 gst/gsturi.h                    |    3 +
 win32/common/libgstreamer.def   |    1 +
 4 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt
index 4787245..3a87827 100644
--- a/docs/gst/gstreamer-sections.txt
+++ b/docs/gst/gstreamer-sections.txt
@@ -2569,6 +2569,7 @@ gst_uri_has_protocol
 gst_uri_get_protocol
 gst_uri_get_location
 gst_uri_construct
+gst_filename_to_uri
 gst_element_make_from_uri
 gst_uri_handler_get_uri_type
 gst_uri_handler_get_protocols
diff --git a/gst/gsturi.c b/gst/gsturi.c
index 247604c..76a1f87 100644
--- a/gst/gsturi.c
+++ b/gst/gsturi.c
@@ -1,6 +1,7 @@
 /* GStreamer
  * Copyright (C) 1999,2000 Erik Walthinsen <omega at cse.ogi.edu>
  *                    2000 Wim Taymans <wtay at chello.be>
+ * Copyright (C) 2011 Tim-Philipp Müller <tim centricular net>
  *
  * gsturi.c: register URI handlers
  *
@@ -782,3 +783,113 @@ gst_uri_handler_new_uri (GstURIHandler * handler, const gchar * uri)
 
   g_signal_emit (handler, gst_uri_handler_signals[NEW_URI], 0, uri);
 }
+
+static gchar *
+gst_file_utils_canonicalise_path (const gchar * path)
+{
+  gchar **parts, **p, *clean_path;
+
+  parts = g_strsplit (path, "/", -1);
+
+  p = parts;
+  while (*p != NULL) {
+    if (strcmp (*p, ".") == 0) {
+      /* just move all following parts on top of this, incl. NUL terminator */
+      g_free (*p);
+      g_memmove (p, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *));
+      /* re-check the new current part again in the next iteration */
+      continue;
+    } else if (strcmp (*p, "..") == 0 && p > parts) {
+      /* just move all following parts on top of the previous part, incl.
+       * NUL terminator */
+      g_free (*(p - 1));
+      g_free (*p);
+      g_memmove (p - 1, p + 1, (g_strv_length (p + 1) + 1) * sizeof (gchar *));
+      /* re-check the new current part again in the next iteration */
+      --p;
+      continue;
+    }
+    ++p;
+  }
+  if (*path == '/') {
+    guint num_parts;
+
+    num_parts = g_strv_length (parts) + 1;      /* incl. terminator */
+    parts = g_renew (gchar *, parts, num_parts + 1);
+    g_memmove (parts + 1, parts, num_parts * sizeof (gchar *));
+    parts[0] = g_strdup ("/");
+  }
+
+  clean_path = g_build_filenamev (parts);
+  g_strfreev (parts);
+  return clean_path;
+}
+
+static gboolean
+file_path_contains_relatives (const gchar * path)
+{
+  return (strstr (path, "/./") != NULL || strstr (path, "/../") != NULL ||
+      strstr (path, G_DIR_SEPARATOR_S "." G_DIR_SEPARATOR_S) != NULL ||
+      strstr (path, G_DIR_SEPARATOR_S ".." G_DIR_SEPARATOR_S) != NULL);
+}
+
+/**
+ * gst_filename_to_uri:
+ * @filename: absolute or relative file name path
+ * @error: pointer to error, or NULL
+ *
+ * Similar to g_filename_to_uri(), but attempts to handle relative file paths
+ * as well. Before converting @filename into an URI, it will be prefixed by
+ * the current working directory if it is a relative path, and then the path
+ * will be canonicalised so that it doesn't contain any './' or '../' segments.
+ *
+ * On Windows #filename should be in UTF-8 encoding.
+ *
+ * Since: 0.10.33
+ */
+gchar *
+gst_filename_to_uri (const gchar * filename, GError ** error)
+{
+  gchar *abs_location = NULL;
+  gchar *uri, *abs_clean;
+
+  g_return_val_if_fail (filename != NULL, NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  if (g_path_is_absolute (filename)) {
+    if (!file_path_contains_relatives (filename)) {
+      uri = g_filename_to_uri (filename, NULL, error);
+      goto beach;
+    }
+
+    abs_location = g_strdup (filename);
+  } else {
+    gchar *cwd;
+
+    cwd = g_get_current_dir ();
+    abs_location = g_build_filename (cwd, filename, NULL);
+    g_free (cwd);
+
+    if (!file_path_contains_relatives (abs_location)) {
+      uri = g_filename_to_uri (abs_location, NULL, error);
+      goto beach;
+    }
+  }
+
+  /* path is now absolute, but contains '.' or '..' */
+#ifndef G_OS_WIN32
+  abs_clean = gst_file_utils_canonicalise_path (abs_location);
+  GST_LOG ("'%s' -> '%s' -> '%s'", filename, abs_location, abs_clean);
+  uri = g_filename_to_uri (abs_clean, NULL, error);
+  g_free (abs_clean);
+#else
+  GST_WARNING ("FIXME: canonicalise win32 path");
+  uri = g_filename_to_uri (abs_location, NULL, error);
+#endif
+
+beach:
+
+  g_free (abs_location);
+  GST_DEBUG ("'%s' -> '%s'", filename, uri);
+  return uri;
+}
diff --git a/gst/gsturi.h b/gst/gsturi.h
index 6193cf3..48a09c0 100644
--- a/gst/gsturi.h
+++ b/gst/gsturi.h
@@ -133,6 +133,9 @@ gchar *		gst_uri_get_location		(const gchar * uri);
 gchar *		gst_uri_construct		(const gchar * protocol,
 						 const gchar * location);
 
+gchar *         gst_filename_to_uri             (const gchar * filename,
+                                                 GError     ** error);
+
 GstElement *	gst_element_make_from_uri	(const GstURIType type,
 						 const gchar *    uri,
 						 const gchar *    elementname);
diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def
index 1e444b9..aae5e2e 100644
--- a/win32/common/libgstreamer.def
+++ b/win32/common/libgstreamer.def
@@ -420,6 +420,7 @@ EXPORTS
 	gst_event_type_get_name
 	gst_event_type_get_type
 	gst_event_type_to_quark
+	gst_filename_to_uri
 	gst_filter_run
 	gst_flow_get_name
 	gst_flow_return_get_type



More information about the gstreamer-commits mailing list