[totem-pl-parser] Write our own horrible path resolution function
- From: Bastien Nocera <hadess src gnome org>
- To: svn-commits-list gnome org
- Subject: [totem-pl-parser] Write our own horrible path resolution function
- Date: Wed, 22 Apr 2009 06:11:01 -0400 (EDT)
commit 7cb7651a1658c4f5a6d4ebc253077467d96203b3
Author: Bastien Nocera <hadess hadess net>
Date: Wed Apr 22 11:09:02 2009 +0100
Write our own horrible path resolution function
And write a few test cases for it. (Closes: #577547)
---
plparse/plparser.symbols | 1 +
plparse/tests/parser.c | 35 ++++++++++
plparse/totem-pl-parser-private.h | 2 +
plparse/totem-pl-parser-smil.c | 8 +-
plparse/totem-pl-parser-wm.c | 17 ++---
plparse/totem-pl-parser-xspf.c | 9 ++-
plparse/totem-pl-parser.c | 137 +++++++++++++++++++++++++++++++++++++
7 files changed, 192 insertions(+), 17 deletions(-)
diff --git a/plparse/plparser.symbols b/plparse/plparser.symbols
index a6942dd..180fe64 100644
--- a/plparse/plparser.symbols
+++ b/plparse/plparser.symbols
@@ -18,6 +18,7 @@ totem_pl_parser_parse_date
totem_pl_parser_parse_duration
totem_pl_parser_parse_with_base
totem_pl_parser_relative
+totem_pl_parser_resolve_uri
totem_pl_parser_result_get_type
totem_pl_parser_type_get_type
totem_pl_parser_write
diff --git a/plparse/tests/parser.c b/plparse/tests/parser.c
index 48f372c..4fa4938 100644
--- a/plparse/tests/parser.c
+++ b/plparse/tests/parser.c
@@ -48,6 +48,40 @@ test_relative (void)
g_assert_cmpstr (test_relative_real ("/1", "/test"), ==, "1");
}
+static char *
+test_resolution_real (const char *base_uri,
+ const char *relative_uri)
+{
+ GFile *base_gfile;
+ char *ret;
+
+ if (base_uri == NULL)
+ base_gfile = NULL;
+ else
+ base_gfile = g_file_new_for_commandline_arg (base_uri);
+
+ ret = totem_pl_parser_resolve_uri (base_gfile, relative_uri);
+ if (base_gfile)
+ g_object_unref (base_gfile);
+
+ return ret;
+}
+
+static void
+test_resolution (void)
+{
+ /* http://bugzilla.gnome.org/show_bug.cgi?id=555417 */
+ g_assert_cmpstr (test_resolution_real ("http://www.yle.fi/player/player.jsp", "288629.asx?s=1000"), ==, "http://www.yle.fi/player/288629.asx?s=1000");
+ g_assert_cmpstr (test_resolution_real ("http://www.yle.fi/player/player.jsp?actionpage=3&id=288629&locale", "288629.asx?s=1000"), ==, "http://www.yle.fi/player/288629.asx?s=1000");
+ /* http://bugzilla.gnome.org/show_bug.cgi?id=577547 */
+ g_assert_cmpstr (test_resolution_real ("http://localhost:12345/8.html", "anim.png"), ==, "http://localhost:12345/anim.png");
+ g_assert_cmpstr (test_resolution_real (NULL, "http://foobar.com/anim.png"), ==, "http://foobar.com/anim.png");
+ g_assert_cmpstr (test_resolution_real ("http://foobar.com/", "/anim.png"), ==, "http://foobar.com/anim.png");
+ g_assert_cmpstr (test_resolution_real ("http://foobar.com/", "anim.png"), ==, "http://foobar.com/anim.png");
+ g_assert_cmpstr (test_resolution_real ("http://foobar.com", "anim.png"), ==, "http://foobar.com/anim.png");
+ g_assert_cmpstr (test_resolution_real ("/foobar/test/", "anim.png"), ==, "file:///foobar/test/anim.png");
+}
+
static void
test_duration (void)
{
@@ -389,6 +423,7 @@ main (int argc, char *argv[])
g_test_add_func ("/parser/duration", test_duration);
g_test_add_func ("/parser/date", test_date);
g_test_add_func ("/parser/relative", test_relative);
+ g_test_add_func ("/parser/resolution", test_resolution);
g_test_add_func ("/parser/parsability", test_parsability);
g_test_add_func ("/parser/parsing/hadess", test_parsing_hadess);
g_test_add_func ("/parser/parsing/nonexistent_files", test_parsing_nonexistent_files);
diff --git a/plparse/totem-pl-parser-private.h b/plparse/totem-pl-parser-private.h
index ddd16c1..d09b4cd 100644
--- a/plparse/totem-pl-parser-private.h
+++ b/plparse/totem-pl-parser-private.h
@@ -110,6 +110,8 @@ gboolean totem_pl_parser_write_buffer (GOutputStream *stream,
GError **error);
char * totem_pl_parser_relative (GFile *output,
const char *filepath);
+char * totem_pl_parser_resolve_uri (GFile *base_gfile,
+ const char *relative_uri);
TotemPlParserResult totem_pl_parser_parse_internal (TotemPlParser *parser,
GFile *file,
GFile *base_file);
diff --git a/plparse/totem-pl-parser-smil.c b/plparse/totem-pl-parser-smil.c
index dc0b575..3850739 100644
--- a/plparse/totem-pl-parser-smil.c
+++ b/plparse/totem-pl-parser-smil.c
@@ -73,12 +73,12 @@ parse_smil_entry (TotemPlParser *parser,
copyright = xml_parser_get_property (node, "copyright");
if (uri != NULL) {
+ char *resolved_uri;
GFile *resolved;
- if (base_file != NULL && strstr (uri, "://") == NULL)
- resolved = g_file_resolve_relative_path (base_file, uri);
- else
- resolved = g_file_new_for_uri (uri);
+ resolved_uri = totem_pl_parser_resolve_uri (base_file, uri);
+ resolved = g_file_new_for_uri (resolved_uri);
+ g_free (resolved_uri);
totem_pl_parser_add_uri (parser,
TOTEM_PL_PARSER_FIELD_FILE, resolved,
diff --git a/plparse/totem-pl-parser-wm.c b/plparse/totem-pl-parser-wm.c
index d177396..beae8d5 100644
--- a/plparse/totem-pl-parser-wm.c
+++ b/plparse/totem-pl-parser-wm.c
@@ -166,6 +166,7 @@ parse_asx_entry (TotemPlParser *parser, GFile *base_file, xml_node_t *parent)
xml_node_t *node;
TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_SUCCESS;
GFile *resolved;
+ char *resolved_uri;
const char *uri;
const char *title, *duration, *starttime, *author;
const char *moreinfo, *abstract, *copyright;
@@ -256,11 +257,9 @@ parse_asx_entry (TotemPlParser *parser, GFile *base_file, xml_node_t *parent)
if (uri == NULL)
return TOTEM_PL_PARSER_RESULT_ERROR;
-
- if (base_file != NULL && strstr (uri, "://") == NULL)
- resolved = g_file_resolve_relative_path (base_file, uri);
- else
- resolved = g_file_new_for_uri (uri);
+ resolved_uri = totem_pl_parser_resolve_uri (base_file, uri);
+ resolved = g_file_new_for_uri (resolved_uri);
+ g_free (resolved_uri);
/* .asx files can contain references to other .asx files */
retval = totem_pl_parser_parse_internal (parser, resolved, NULL);
@@ -289,16 +288,16 @@ parse_asx_entryref (TotemPlParser *parser, GFile *base_file, xml_node_t *node)
TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_SUCCESS;
const char *uri;
GFile *resolved;
+ char *resolved_uri;
uri = xml_parser_get_property (node, "href");
if (uri == NULL)
return TOTEM_PL_PARSER_RESULT_ERROR;
- if (base_file != NULL && strstr (uri, "://") == NULL)
- resolved = g_file_resolve_relative_path (base_file, uri);
- else
- resolved = g_file_new_for_uri (uri);
+ resolved_uri = totem_pl_parser_resolve_uri (base_file, uri);
+ resolved = g_file_new_for_uri (resolved_uri);
+ g_free (resolved_uri);
/* .asx files can contain references to other .asx files */
retval = totem_pl_parser_parse_internal (parser, resolved, NULL);
diff --git a/plparse/totem-pl-parser-xspf.c b/plparse/totem-pl-parser-xspf.c
index 89ebb08..434b095 100644
--- a/plparse/totem-pl-parser-xspf.c
+++ b/plparse/totem-pl-parser-xspf.c
@@ -164,6 +164,7 @@ parse_xspf_track (TotemPlParser *parser, GFile *base_file, xmlDocPtr doc,
xmlChar *title, *uri, *image_uri, *artist, *album, *duration, *moreinfo;
xmlChar *download_uri, *id;
GFile *resolved;
+ char *resolved_uri;
TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_ERROR;
title = NULL;
@@ -217,10 +218,10 @@ parse_xspf_track (TotemPlParser *parser, GFile *base_file, xmlDocPtr doc,
goto bail;
}
- if (base_file != NULL && strstr ((char *) uri, "://") == NULL)
- resolved = g_file_resolve_relative_path (base_file, (const char *) uri);
- else
- resolved = g_file_new_for_uri ((const char *) uri);
+ resolved_uri = totem_pl_parser_resolve_uri (base_file, (char *) uri);
+ resolved = g_file_new_for_uri (resolved_uri);
+ g_free (resolved_uri);
+
totem_pl_parser_add_uri (parser,
TOTEM_PL_PARSER_FIELD_FILE, resolved,
TOTEM_PL_PARSER_FIELD_TITLE, title,
diff --git a/plparse/totem-pl-parser.c b/plparse/totem-pl-parser.c
index 4645e2f..2b4d21b 100644
--- a/plparse/totem-pl-parser.c
+++ b/plparse/totem-pl-parser.c
@@ -858,6 +858,143 @@ totem_pl_parser_relative (GFile *output, const char *filepath)
return retval;
}
+static char *
+relative_uri_remove_query (const char *uri, char **query)
+{
+ char *qmark;
+
+ /* Look for '?' */
+ qmark = strrchr (uri, '?');
+ if (qmark == NULL)
+ return NULL;
+
+ if (query != NULL)
+ *query = g_strdup (qmark);
+ return g_strndup (uri, qmark - uri);
+}
+
+static const char *suffixes[] = {
+ ".jsp",
+ ".php",
+ ".asp"
+};
+
+static gboolean
+is_probably_dir (const char *filename)
+{
+ gboolean ret;
+ char *content_type, *short_name;
+
+ short_name = relative_uri_remove_query (filename, NULL);
+ if (short_name == NULL)
+ short_name = g_strdup (filename);
+ content_type = g_content_type_guess (short_name, NULL, -1, NULL);
+ if (g_content_type_is_unknown (content_type) != FALSE) {
+ guint i;
+ for (i = 0; i < G_N_ELEMENTS (suffixes); i++) {
+ if (g_str_has_suffix (short_name, suffixes[i]) != FALSE) {
+ g_free (content_type);
+ g_free (short_name);
+ return FALSE;
+ }
+ }
+ ret = TRUE;
+ } else {
+ ret = FALSE;
+ }
+ g_free (content_type);
+ g_free (short_name);
+
+ return ret;
+}
+
+char *
+totem_pl_parser_resolve_uri (GFile *base_gfile,
+ const char *relative_uri)
+{
+ char *uri, *scheme, *query, *new_relative_uri, *base_uri;
+ GFile *base_parent_gfile, *resolved_gfile;
+
+ if (relative_uri == NULL) {
+ if (base_gfile == NULL)
+ return NULL;
+ return g_file_get_uri (base_gfile);
+ }
+
+ if (base_gfile == NULL)
+ return g_strdup (relative_uri);
+
+ /* If |relative_uri| has a scheme, it's a full URI, just return it */
+ scheme = g_uri_parse_scheme (relative_uri);
+ if (scheme != NULL) {
+ g_free (scheme);
+ return g_strdup (relative_uri);
+ }
+
+ /* Check whether we need to get the parent for the base or not */
+ base_uri = g_file_get_path (base_gfile);
+ if (base_uri == NULL)
+ base_uri = g_file_get_uri (base_gfile);
+ if (is_probably_dir (base_uri) == FALSE)
+ base_parent_gfile = g_file_get_parent (base_gfile);
+ else
+ base_parent_gfile = g_object_ref (base_gfile);
+ g_free (base_uri);
+
+ if (base_parent_gfile == NULL) {
+ resolved_gfile = g_file_resolve_relative_path (base_gfile, relative_uri);
+ uri = g_file_get_uri (resolved_gfile);
+ g_object_unref (resolved_gfile);
+ return uri;
+ }
+
+ /* Remove the query portion of the URI, to transplant it again
+ * if there is any */
+ query = NULL;
+ new_relative_uri = relative_uri_remove_query (relative_uri, &query);
+
+ if (new_relative_uri) {
+ char *tmpuri;
+
+ resolved_gfile = g_file_resolve_relative_path (base_parent_gfile, new_relative_uri);
+ g_object_unref (base_parent_gfile);
+ if (!resolved_gfile) {
+ char *base_uri;
+ base_uri = g_file_get_uri (base_gfile);
+ g_warning ("Failed to resolve relative URI '%s' against base '%s'\n", relative_uri, base_uri);
+ g_free (base_uri);
+ g_free (new_relative_uri);
+ g_free (query);
+ return NULL;
+ }
+
+ tmpuri = g_file_get_uri (resolved_gfile);
+ g_object_unref (resolved_gfile);
+ uri = g_strdup_printf ("%s%s", tmpuri, query);
+
+ g_free (tmpuri);
+ g_free (new_relative_uri);
+ g_free (query);
+
+ return uri;
+ } else {
+ resolved_gfile = g_file_resolve_relative_path (base_parent_gfile, relative_uri);
+ g_object_unref (base_parent_gfile);
+ if (!resolved_gfile) {
+ char *base_uri;
+ base_uri = g_file_get_uri (base_gfile);
+ g_warning ("Failed to resolve relative URI '%s' against base '%s'\n", relative_uri, base_uri);
+ g_free (base_uri);
+ return NULL;
+ }
+
+ uri = g_file_get_uri (resolved_gfile);
+ g_object_unref (resolved_gfile);
+
+ return uri;
+ }
+}
+
#ifndef TOTEM_PL_PARSER_MINI
/**
* totem_pl_parser_write_with_title:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]