+2007-09-12 Tim-Philipp Müller <tim at centricular dot net>
+
+ * gst/gsturi.c: (gst_uri_get_location):
+ If there's no hostname, we want to return 'c:/foo/bar.txt'
+ and not '/c:/foo/bar.txt' on Windows. Fixes #469402.
+
+ * tests/check/gst/gsturi.c:
+ Unit test for the above and a few more things.
+
2007-09-11 Wim Taymans <wim.taymans@gmail.com>
* docs/design/part-live-source.txt:
* gst_uri_get_location:
* @uri: A URI string
*
- * Extracts the location out of a given valid URI. So the protocol and "://"
- * are stripped from the URI. The returned string must be freed using
+ * Extracts the location out of a given valid URI, ie. the protocol and "://"
+ * are stripped from the URI, which means that the location returned includes
+ * the hostname if one is specified. The returned string must be freed using
* g_free().
*
- * Returns: The location for this URI. Returns NULL if the URI isn't valid.
+ * Returns: The location for this URI. Returns NULL if the URI isn't valid. If
+ * the URI does not contain a location, an empty string is returned.
*/
gchar *
gst_uri_get_location (const gchar * uri)
{
- gchar *colon;
- gchar *location, *unescaped;
+ const gchar *colon;
+ gchar *unescaped = NULL;
g_return_val_if_fail (uri != NULL, NULL);
g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
colon = strstr (uri, "://");
- location = g_strdup (colon + 3);
-
- unescaped = unescape_string (location, "/");
- g_free (location);
+ unescaped = unescape_string (colon + 3, "/");
+
+ /* On Windows an URI might look like file:///c:/foo/bar.txt or
+ * file:///c|/foo/bar.txt (some Netscape versions) and we want to
+ * return c:/foo/bar.txt as location rather than /c:/foo/bar.txt.
+ * Can't use g_filename_from_uri() here because it will only handle the
+ * file:// protocol */
+#ifdef G_OS_WIN32
+ if (unescaped != NULL && unescaped[0] == '/' &&
+ g_ascii_isalpha (unescaped[1]) &&
+ (unescaped[2] == ':' || unescaped[2] == '|')) {
+ unescaped[2] = ':';
+ g_memmove (unescaped, unescaped + 1, strlen (unescaped + 1) + 1);
+ }
+#endif
+ GST_LOG ("extracted location '%s' from URI '%s'", GST_STR_NULL (unescaped),
+ uri);;
return unescaped;
}
GST_END_TEST;
+GST_START_TEST (test_uri_get_location)
+{
+ gchar *l;
+
+ /* URI with no location should return empty string */
+ l = gst_uri_get_location ("dvd://");
+ fail_unless (l != NULL);
+ fail_unless_equals_string (l, "");
+ g_free (l);
+
+ /* URI with hostname */
+ l = gst_uri_get_location ("smb://supercomputer/path/to/file");
+ fail_unless (l != NULL);
+ fail_unless_equals_string (l, "supercomputer/path/to/file");
+ g_free (l);
+
+ /* URI */
+ l = gst_uri_get_location ("file:///path/to/file");
+ fail_unless (l != NULL);
+ fail_unless_equals_string (l, "/path/to/file");
+ g_free (l);
+
+ /* unescaping */
+ l = gst_uri_get_location ("file:///path/to/some%20file");
+ fail_unless (l != NULL);
+ fail_unless_equals_string (l, "/path/to/some file");
+ g_free (l);
+}
+
+GST_END_TEST;
+
+#ifdef G_OS_WIN32
+
+GST_START_TEST (test_win32_uri)
+{
+ gchar *uri, *l;
+
+ uri = g_strdup ("file:///c:/my%20music/foo.ogg");
+ l = gst_uri_get_location (uri);
+ fail_unless (l != NULL);
+ /* fail_unless_equals_string will screw up here in the failure case
+ * because the string constant will be appended to the printf format
+ * message string and contains a '%', that's why we use fail_unless here */
+ fail_unless (g_str_equal (l, "c:/my music/foo.ogg"),
+ "wrong location '%s' returned for URI '%s'", l, uri);
+ g_free (l);
+ g_free (uri);
+
+}
+
+GST_END_TEST;
+
+#endif /* G_OS_WIN32 */
+
static Suite *
gst_uri_suite (void)
{
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_protocol_case);
+ tcase_add_test (tc_chain, test_uri_get_location);
+#ifdef G_OS_WIN32
+ tcase_add_test (tc_chain, test_win32_uri);
+#endif
+
return s;
}