[totem-pl-parser] plparse: Simplify ITMS link parsing



commit 71eaa864fe06f76398807ac3befd7b8576839347
Author: Bastien Nocera <hadess hadess net>
Date:   Fri Apr 15 15:47:43 2016 +0200

    plparse: Simplify ITMS link parsing
    
    Instead of simply following the link and trying to guess what the end
    format might be, parse the ITMS ID from the link, and grab the RSS
    URL from the resulting json.
    
    With inspiration from:
    https://github.com/vocalapp/vocal/blob/master/src/Utils/iTunesProvider.vala

 plparse/totem-pl-parser-podcast.c |  182 +++++++++----------------------------
 1 files changed, 43 insertions(+), 139 deletions(-)
---
diff --git a/plparse/totem-pl-parser-podcast.c b/plparse/totem-pl-parser-podcast.c
index 9fa68ac..01e7263 100644
--- a/plparse/totem-pl-parser-podcast.c
+++ b/plparse/totem-pl-parser-podcast.c
@@ -603,87 +603,15 @@ totem_pl_parser_add_xml_feed (TotemPlParser *parser,
 #endif /* !HAVE_GMIME */
 }
 
-static GByteArray *
-totem_pl_parser_load_http_itunes (const char *uri,
-                                 gboolean    debug)
-{
-       SoupMessage *msg;
-       SoupSession *session;
-       GByteArray *data;
-
-       if (debug)
-               g_print ("Loading ITMS playlist '%s'\n", uri);
-
-       session = soup_session_sync_new_with_options (
-           SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER,
-           SOUP_SESSION_USER_AGENT, "iTunes/10.0.0",
-           SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
-           NULL);
-
-       msg = soup_message_new (SOUP_METHOD_GET, uri);
-       soup_session_send_message (session, msg);
-       if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-               data = g_byte_array_new ();
-               g_byte_array_append (data,
-                                    (guchar *) msg->response_body->data,
-                                    msg->response_body->length);
-       } else {
-               return NULL;
-       }
-       g_object_unref (msg);
-       g_object_unref (session);
-
-       return data;
-}
-
-static const char *
-totem_pl_parser_parse_plist (xml_node_t *item)
-{
-       for (item = item->child; item != NULL; item = item->next) {
-               /* What we're looking for looks like:
-                *  <key>action</key>
-                *  <dict>
-                *    <key>kind</key><string>Goto</string>
-                *    <key>url</key><string>URL</string>
-                */
-               if (g_ascii_strcasecmp (item->name, "key") == 0
-                   && g_ascii_strcasecmp (item->data, "action") == 0) {
-                       xml_node_t *node = item->next;
-
-                       if (node && g_ascii_strcasecmp (node->name, "[CDATA]") == 0)
-                               node = node->next;
-                       if (node && g_ascii_strcasecmp (node->name, "dict") == 0) {
-                               for (node = node->child; node != NULL; node = node->next) {
-                                       if (g_ascii_strcasecmp (node->name, "key") == 0 &&
-                                           g_ascii_strcasecmp (node->data, "url") == 0 &&
-                                           node->next != NULL) {
-                                               node = node->next;
-                                               if (g_ascii_strcasecmp (node->name, "string") == 0)
-                                                       return node->data;
-                                       }
-                               }
-                       }
-               } else {
-                       const char *ret;
-
-                       ret = totem_pl_parser_parse_plist (item);
-                       if (ret != NULL)
-                               return ret;
-               }
-       }
-
-       return NULL;
-}
-
 static char *
-totem_pl_parser_parse_html (char *data, gsize len, gboolean debug)
+totem_pl_parser_parse_json (char *data, gsize len, gboolean debug)
 {
        char *s, *end;
 
-       s = g_strstr_len (data, len, "feed-url=\"");
+       s = g_strstr_len (data, len, "feedUrl\":\"");
        if (s == NULL)
                return NULL;
-       s += strlen ("feed-url=\"");
+       s += strlen ("feedUrl\":\"");
        if (*s == '\0')
                return NULL;
        end = g_strstr_len (s, len - (s - data), "\"");
@@ -692,59 +620,33 @@ totem_pl_parser_parse_html (char *data, gsize len, gboolean debug)
        return g_strndup (s, end - s);
 }
 
-static GFile *
-totem_pl_parser_get_feed_uri (char *data, gsize len, gboolean debug)
+static char *
+get_itms_id (GFile *file)
 {
-       xml_node_t* doc;
-       const char *uri;
-       GFile *ret = NULL;
-       GByteArray *content;
-
-       uri = NULL;
-
-       /* Probably HTML, look for feed-url */
-       if (g_strstr_len (data, len, "feed-url") != NULL) {
-               char *feed_uri;
-               feed_uri = totem_pl_parser_parse_html (data, len, debug);
-               if (debug)
-                       g_print ("Found feed-url in HTML: '%s'\n", feed_uri);
-               if (feed_uri == NULL)
-                       return NULL;
-               ret = g_file_new_for_uri (feed_uri);
-               g_free (feed_uri);
-               return ret;
-       }
+       char *uri, *start, *end, *id;
 
-       doc = totem_pl_parser_parse_xml_relaxed (data, len);
-       if (doc == NULL)
+       uri = g_file_get_uri (file);
+       if (!uri)
                return NULL;
 
-       /* If the document has no name */
-       if (doc->name == NULL || g_ascii_strcasecmp (doc->name, "plist") != 0)
-               goto out;
-
-       /* Redirect plist? Find a goto action */
-       uri = totem_pl_parser_parse_plist (doc);
-
-       if (debug) {
-               if (uri == NULL)
-                       g_print ("Did not find redirect URL in: %.*s\n", (int) len, data);
-               else
-                       g_print ("Found redirect URL: %s\n", uri);
+       start = strstr (uri, "/id");
+       if (!start) {
+               g_free (uri);
+               return NULL;
        }
 
-       if (uri == NULL)
-               goto out;
+       end = strchr (start, '?');
+       if (!end)
+               end = strchr (start, '#');
+       if (!end || end - start <= 3) {
+               g_free (uri);
+               return NULL;
+       }
 
-       content = totem_pl_parser_load_http_itunes (uri, debug);
-       if (!content)
-               goto out;
-       ret = totem_pl_parser_get_feed_uri ((char *) content->data, content->len, debug);
-       g_byte_array_free (content, TRUE);
+       id = g_strndup (start + 3, end - start - 3);
+       g_free (uri);
 
-out:
-       xml_parser_free_tree (doc);
-       return ret;
+       return id;
 }
 
 TotemPlParserResult
@@ -757,35 +659,37 @@ totem_pl_parser_add_itms (TotemPlParser *parser,
 #ifndef HAVE_GMIME
        WARN_NO_GMIME;
 #else
-       GByteArray *content;
-       char *itms_uri;
-       GFile *feed_file;
+       GFile *json_file, *feed_file;
        TotemPlParserResult ret;
+       char *contents, *id, *json_uri, *feed_url;
+       gsize len;
 
-       if (g_file_has_uri_scheme (file, "itms") != FALSE ||
-           g_file_has_uri_scheme (file, "itmss") != FALSE) {
-               itms_uri= g_file_get_uri (file);
-               memcpy (itms_uri, "http", 4);
-       } else if (g_file_has_uri_scheme (file, "http") != FALSE) {
-               itms_uri = g_file_get_uri (file);
-       } else {
+       id = get_itms_id (file);
+       if (id == NULL) {
+               DEBUG(file, g_print ("Could not get ITMS ID for URL '%s'", uri));
                return TOTEM_PL_PARSER_RESULT_ERROR;
        }
 
-       /* Load the file using iTunes user-agent */
-       content = totem_pl_parser_load_http_itunes (itms_uri, totem_pl_parser_is_debugging_enabled (parser));
-       g_free (itms_uri);
+       DEBUG(file, g_print ("Got ID '%s' for URL '%s'", id, uri));
 
-       if (!content)
+       json_uri = g_strdup_printf ("https://itunes.apple.com/lookup?id=%s&entity=podcast";, id);
+       g_free (id);
+       json_file = g_file_new_for_uri (json_uri);
+       g_free (json_uri);
+
+       if (g_file_load_contents (json_file, NULL, &contents, &len, NULL, NULL) == FALSE) {
+               g_object_unref (json_file);
                return TOTEM_PL_PARSER_RESULT_ERROR;
+       }
 
-       /* And look in the file for the feedURL */
-       feed_file = totem_pl_parser_get_feed_uri ((char *) content->data, content->len,
-                                                 totem_pl_parser_is_debugging_enabled (parser));
-       g_byte_array_free (content, TRUE);
-       if (feed_file == NULL)
+       feed_url = totem_pl_parser_parse_json (contents, len, totem_pl_parser_is_debugging_enabled (parser));
+       g_free (contents);
+       if (feed_url == NULL)
                return TOTEM_PL_PARSER_RESULT_ERROR;
 
+       feed_file = g_file_new_for_uri (feed_url);
+       g_free (feed_url);
+
        DEBUG(feed_file, g_print ("Found feed URI: %s\n", uri));
 
        ret = totem_pl_parser_add_rss (parser, feed_file, NULL, parse_data, NULL);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]