mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
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()
This commit is contained in:
parent
b3f0d98964
commit
27027a2dd2
4 changed files with 116 additions and 0 deletions
|
@ -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
|
||||
|
|
111
gst/gsturi.c
111
gst/gsturi.c
|
@ -1,6 +1,7 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000 Wim Taymans <wtay@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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue