gst/gsturi.c: If there's no hostname, we want to return 'c:/foo/bar.txt' and not...
authorTim-Philipp Müller <tim@centricular.net>
Wed, 12 Sep 2007 12:36:51 +0000 (12:36 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Wed, 12 Sep 2007 12:36:51 +0000 (12:36 +0000)
Original commit message from CVS:
* 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.

ChangeLog
gst/gsturi.c
tests/check/gst/gsturi.c

index f50c3a9..a6d5016 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+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:
index ec8f2e5..31f8f1c 100644 (file)
@@ -404,28 +404,43 @@ gst_uri_has_protocol (const gchar * uri, const gchar * protocol)
  * 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;
 }
 
index d54d9f4..111149f 100644 (file)
@@ -39,6 +39,60 @@ GST_START_TEST (test_protocol_case)
 
 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)
 {
@@ -49,6 +103,11 @@ 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;
 }