static TotemPlParserResult parse_opml_outline (TotemPlParser *parser, xml_node_t *parent) { xml_node_t* node; for (node = parent->child; node != NULL; node = node->next) { const char *title, *uri; if (node->name == NULL || g_ascii_strcasecmp (node->name, "outline") != 0) continue; uri = xml_parser_get_property (node, "xmlUrl"); title = xml_parser_get_property (node, "text"); if (uri == NULL) continue; totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_TITLE, title, TOTEM_PL_PARSER_FIELD_URI, uri, NULL); } return TOTEM_PL_PARSER_RESULT_SUCCESS; }
static gboolean parse_asx_entryref (XplayerPlParser *parser, GFile *base_file, xml_node_t *node, XplayerPlParseData *parse_data) { XplayerPlParserResult retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; const char *uri; GFile *resolved; char *resolved_uri; uri = xml_parser_get_property (node, "href"); if (uri == NULL) return XPLAYER_PL_PARSER_RESULT_ERROR; resolved_uri = xplayer_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 = xplayer_pl_parser_parse_internal (parser, resolved, NULL, parse_data); if (retval != XPLAYER_PL_PARSER_RESULT_SUCCESS) { xplayer_pl_parser_add_uri (parser, XPLAYER_PL_PARSER_FIELD_FILE, resolved, NULL); retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; } g_object_unref (resolved); return retval; }
int xml_parser_get_property_bool (const xml_node_t *node, const char *name, int def_value) { const char *v; v = xml_parser_get_property (node, name); if (!v) return def_value; return !strcasecmp (v, "true"); }
static const char* parse_smil_head (XplayerPlParser *parser, xml_node_t *doc, xml_node_t *parent) { xml_node_t *node; const char *title; title = NULL; for (node = parent->child; node != NULL; node = node->next) { if (g_ascii_strcasecmp (node->name, "meta") == 0) { const char *prop; prop = xml_parser_get_property (node, "name"); if (prop != NULL && g_ascii_strcasecmp (prop, "title") == 0) { title = xml_parser_get_property (node, "content"); if (title != NULL) break; } } } return title; }
int xml_parser_get_property_int (const xml_node_t *node, const char *name, int def_value) { const char *v; int ret; v = xml_parser_get_property (node, name); if (!v) return def_value; if (sscanf (v, "%d", &ret) != 1) return def_value; else return ret; }
static XplayerPlParserResult parse_smil_entry (XplayerPlParser *parser, GFile *base_file, xml_node_t *doc, xml_node_t *parent, const char *parent_title) { xml_node_t *node; const char *title, *uri, *author, *abstract, *dur, *clip_begin, *copyright, *subtitle_uri; XplayerPlParserResult retval = XPLAYER_PL_PARSER_RESULT_ERROR; gboolean added; title = NULL; uri = NULL; subtitle_uri = NULL; author = NULL; abstract = NULL; dur = NULL; clip_begin = NULL; copyright = NULL; added = FALSE; for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; /* ENTRY should only have one ref and one title nodes */ if (g_ascii_strcasecmp (node->name, "video") == 0 || g_ascii_strcasecmp (node->name, "audio") == 0 || g_ascii_strcasecmp (node->name, "media") == 0) { /* Send the previous entry */ if (uri != NULL && added == FALSE) { parse_smil_entry_add (parser, base_file, uri, title ? title : parent_title, abstract, copyright, author, clip_begin, dur, subtitle_uri); added = TRUE; retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; } uri = xml_parser_get_property (node, "src"); title = xml_parser_get_property (node, "title"); author = xml_parser_get_property (node, "author"); dur = xml_parser_get_property (node, "dur"); clip_begin = xml_parser_get_property (node, "clip-begin"); abstract = xml_parser_get_property (node, "abstract"); copyright = xml_parser_get_property (node, "copyright"); subtitle_uri = NULL; added = FALSE; } else if (g_ascii_strcasecmp (node->name, "textstream") == 0) { subtitle_uri = xml_parser_get_property (node, "src"); } else { if (parse_smil_entry (parser, base_file, doc, node, parent_title) != FALSE) retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; } } if (uri != NULL && added == FALSE) { parse_smil_entry_add (parser, base_file, uri, title ? title : parent_title, abstract, copyright, author, clip_begin, dur, subtitle_uri); added = TRUE; retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; } return retval; }
static gboolean parse_asx_entries (XplayerPlParser *parser, const char *uri, GFile *base_file, xml_node_t *parent, XplayerPlParseData *parse_data) { char *title = NULL; GFile *new_base; xml_node_t *node; XplayerPlParserResult retval = XPLAYER_PL_PARSER_RESULT_ERROR; new_base = NULL; /* Loop to look for playlist information first */ for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "title") == 0) { g_free (title); title = g_strdup (node->data); xplayer_pl_parser_add_uri (parser, XPLAYER_PL_PARSER_FIELD_IS_PLAYLIST, TRUE, XPLAYER_PL_PARSER_FIELD_URI, uri, XPLAYER_PL_PARSER_FIELD_TITLE, title, NULL); } if (g_ascii_strcasecmp (node->name, "base") == 0) { const char *str; str = xml_parser_get_property (node, "href"); if (str != NULL) { if (new_base != NULL) g_object_unref (new_base); new_base = g_file_new_for_uri (str); } } } /* Restart for the entries now */ for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "entry") == 0) { /* Whee! found an entry here, find the REF and TITLE */ if (parse_asx_entry (parser, new_base ? new_base : base_file, node, parse_data) != FALSE) retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; } if (g_ascii_strcasecmp (node->name, "entryref") == 0) { /* Found an entryref, extract the REF attribute */ if (parse_asx_entryref (parser, new_base ? new_base : base_file, node, parse_data) != FALSE) retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; } if (g_ascii_strcasecmp (node->name, "repeat") == 0) { /* Repeat at the top-level */ if (parse_asx_entries (parser, uri, new_base ? new_base : base_file, node, parse_data) != FALSE) retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; } } if (new_base != NULL) g_object_unref (new_base); if (title != NULL) xplayer_pl_parser_playlist_end (parser, uri); g_free (title); return retval; }
static gboolean parse_asx_entry (XplayerPlParser *parser, GFile *base_file, xml_node_t *parent, XplayerPlParseData *parse_data) { xml_node_t *node; XplayerPlParserResult retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; GFile *resolved; char *resolved_uri; const char *uri; const char *title, *duration, *starttime, *author; const char *moreinfo, *abstract, *copyright; title = NULL; uri = NULL; duration = NULL; starttime = NULL; moreinfo = NULL; abstract = NULL; copyright = NULL; author = NULL; for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; /* ENTRY can only have one title node but multiple REFs */ if (g_ascii_strcasecmp (node->name, "ref") == 0) { const char *tmp; tmp = xml_parser_get_property (node, "href"); if (tmp == NULL) continue; /* FIXME, should we prefer mms streams, or non-mms? * See bug #352559 */ if (uri == NULL) uri = tmp; continue; } if (g_ascii_strcasecmp (node->name, "title") == 0) title = node->data; if (g_ascii_strcasecmp (node->name, "author") == 0) author = node->data; if (g_ascii_strcasecmp (node->name, "moreinfo") == 0) { const char *tmp; tmp = xml_parser_get_property (node, "href"); if (tmp == NULL) continue; moreinfo = tmp; } if (g_ascii_strcasecmp (node->name, "copyright") == 0) copyright = node->data; if (g_ascii_strcasecmp (node->name, "abstract") == 0) abstract = node->data; if (g_ascii_strcasecmp (node->name, "duration") == 0) { const char *tmp; tmp = xml_parser_get_property (node, "value"); if (tmp == NULL) continue; duration = tmp; } if (g_ascii_strcasecmp (node->name, "starttime") == 0) { const char *tmp; tmp = xml_parser_get_property (node, "value"); if (tmp == NULL) continue; starttime = tmp; } if (g_ascii_strcasecmp (node->name, "param") == 0) { const char *name, *value; name = xml_parser_get_property (node, "name"); if (name == NULL || g_ascii_strcasecmp (name, "showwhilebuffering") != 0) continue; value = xml_parser_get_property (node, "value"); if (value == NULL || g_ascii_strcasecmp (value, "true") != 0) continue; /* We ignore items that are the buffering images */ retval = XPLAYER_PL_PARSER_RESULT_IGNORED; goto bail; } } if (uri == NULL) return XPLAYER_PL_PARSER_RESULT_ERROR; resolved_uri = xplayer_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 = xplayer_pl_parser_parse_internal (parser, resolved, NULL, parse_data); if (retval != XPLAYER_PL_PARSER_RESULT_SUCCESS) { xplayer_pl_parser_add_uri (parser, XPLAYER_PL_PARSER_FIELD_FILE, resolved, XPLAYER_PL_PARSER_FIELD_TITLE, title, XPLAYER_PL_PARSER_FIELD_ABSTRACT, abstract, XPLAYER_PL_PARSER_FIELD_COPYRIGHT, copyright, XPLAYER_PL_PARSER_FIELD_AUTHOR, author, XPLAYER_PL_PARSER_FIELD_STARTTIME, starttime, XPLAYER_PL_PARSER_FIELD_DURATION, duration, XPLAYER_PL_PARSER_FIELD_MOREINFO, moreinfo, NULL); retval = XPLAYER_PL_PARSER_RESULT_SUCCESS; } g_object_unref (resolved); bail: return retval; }
/* Atom docs: * http://www.atomenabled.org/developers/syndication/atom-format-spec.php#rfc.section.4.1 * http://tools.ietf.org/html/rfc4287 * http://tools.ietf.org/html/rfc4946 */ static TotemPlParserResult parse_atom_entry (TotemPlParser *parser, xml_node_t *parent) { const char *title, *author, *uri, *filesize; const char *copyright, *pub_date, *description, *img; xml_node_t *node; title = author = uri = filesize = NULL; copyright = pub_date = description = img = NULL; for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "title") == 0) { title = node->data; } else if (g_ascii_strcasecmp (node->name, "author") == 0) { xml_node_t *child; for (child = node->child; child != NULL; child = child->next) { if (child->name == NULL) continue; if (g_ascii_strcasecmp (child->name, "name") == 0) { author = child->data; break; } } } else if (g_ascii_strcasecmp (node->name, "link") == 0) { const char *rel; //FIXME how do we choose the default enclosure type? rel = xml_parser_get_property (node, "rel"); if (g_ascii_strcasecmp (rel, "enclosure") == 0) { const char *href; //FIXME what's the difference between url and href there? href = xml_parser_get_property (node, "href"); if (href == NULL) continue; uri = href; filesize = xml_parser_get_property (node, "length"); } else if (g_ascii_strcasecmp (rel, "license") == 0) { const char *href; href = xml_parser_get_property (node, "href"); if (href == NULL) continue; /* This isn't really a copyright, but what the hey */ copyright = href; } else if (g_ascii_strcasecmp (rel, "alternate") == 0) { const char *href; href = xml_parser_get_property (node, "href"); if (href == NULL) continue; if (!totem_pl_parser_is_videosite (href, FALSE)) continue; uri = href; } } else if (g_ascii_strcasecmp (node->name, "updated") == 0 || (g_ascii_strcasecmp (node->name, "modified") == 0 && pub_date == NULL)) { pub_date = node->data; } else if (g_ascii_strcasecmp (node->name, "summary") == 0 || (g_ascii_strcasecmp (node->name, "content") == 0 && description == NULL)) { const char *type; type = xml_parser_get_property (node, "content"); if (type != NULL && g_ascii_strcasecmp (type, "text/plain") == 0) description = node->data; } else if (g_ascii_strcasecmp (node->name, "media:group") == 0) { xml_node_t *child; for (child = node->child; child != NULL; child = child->next) { if (child->name == NULL) continue; if (g_ascii_strcasecmp (child->name, "media:title") == 0 && title == NULL) { title = child->data; } else if (g_ascii_strcasecmp (child->name, "media:description") == 0 && description == NULL) { description = child->data; } else if (g_ascii_strcasecmp (child->name, "media:content") == 0 && uri == NULL) { const char *prop; prop = xml_parser_get_property (child, "url"); if (prop == NULL) continue; if (!totem_pl_parser_is_videosite (prop, FALSE)) continue; uri = prop; } else if (g_ascii_strcasecmp (child->name, "media:thumbnail") == 0) { img = xml_parser_get_property (child, "url"); } } } //FIXME handle category } if (uri != NULL) { totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_TITLE, title, TOTEM_PL_PARSER_FIELD_AUTHOR, author, TOTEM_PL_PARSER_FIELD_URI, uri, TOTEM_PL_PARSER_FIELD_FILESIZE, filesize, TOTEM_PL_PARSER_FIELD_COPYRIGHT, copyright, TOTEM_PL_PARSER_FIELD_PUB_DATE, pub_date, TOTEM_PL_PARSER_FIELD_DESCRIPTION, description, TOTEM_PL_PARSER_FIELD_IMAGE_URI, img, NULL); } return TOTEM_PL_PARSER_RESULT_SUCCESS; }
static TotemPlParserResult parse_rss_items (TotemPlParser *parser, const char *uri, xml_node_t *parent) { const char *title, *language, *description, *author; const char *contact, *img, *pub_date, *copyright; xml_node_t *node; title = language = description = author = NULL; contact = img = pub_date = copyright = NULL; /* We need to parse for the feed metadata first, then for the items */ for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "title") == 0) { title = node->data; } else if (g_ascii_strcasecmp (node->name, "language") == 0) { language = node->data; } else if (g_ascii_strcasecmp (node->name, "description") == 0 || g_ascii_strcasecmp (node->name, "itunes:subtitle") == 0) { description = node->data; } else if (g_ascii_strcasecmp (node->name, "author") == 0 || g_ascii_strcasecmp (node->name, "itunes:author") == 0 || (g_ascii_strcasecmp (node->name, "generator") == 0 && author == NULL)) { author = node->data; } else if (g_ascii_strcasecmp (node->name, "webMaster") == 0) { contact = node->data; } else if (g_ascii_strcasecmp (node->name, "image") == 0) { img = node->data; } else if (g_ascii_strcasecmp (node->name, "itunes:image") == 0) { const char *href; href = xml_parser_get_property (node, "href"); if (href != NULL) img = href; } else if (g_ascii_strcasecmp (node->name, "lastBuildDate") == 0 || g_ascii_strcasecmp (node->name, "pubDate") == 0) { pub_date = node->data; } else if (g_ascii_strcasecmp (node->name, "copyright") == 0) { copyright = node->data; } } /* Send the info we already have about the feed */ totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_IS_PLAYLIST, TRUE, TOTEM_PL_PARSER_FIELD_URI, uri, TOTEM_PL_PARSER_FIELD_TITLE, title, TOTEM_PL_PARSER_FIELD_LANGUAGE, language, TOTEM_PL_PARSER_FIELD_DESCRIPTION, description, TOTEM_PL_PARSER_FIELD_AUTHOR, author, TOTEM_PL_PARSER_FIELD_PUB_DATE, pub_date, TOTEM_PL_PARSER_FIELD_COPYRIGHT, copyright, TOTEM_PL_PARSER_FIELD_IMAGE_URI, img, TOTEM_PL_PARSER_FIELD_CONTACT, contact, NULL); for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "item") == 0) parse_rss_item (parser, node); } totem_pl_parser_playlist_end (parser, uri); return TOTEM_PL_PARSER_RESULT_SUCCESS; }
static TotemPlParserResult parse_rss_item (TotemPlParser *parser, xml_node_t *parent) { const char *title, *uri, *description, *author, *img; const char *pub_date, *duration, *filesize, *content_type, *id; xml_node_t *node; title = uri = description = author = content_type = NULL; img = pub_date = duration = filesize = id = NULL; for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "title") == 0) { title = node->data; } else if (g_ascii_strcasecmp (node->name, "url") == 0) { uri = node->data; } else if (g_ascii_strcasecmp (node->name, "pubDate") == 0) { pub_date = node->data; } else if (g_ascii_strcasecmp (node->name, "guid") == 0) { id = node->data; } else if (g_ascii_strcasecmp (node->name, "description") == 0 || g_ascii_strcasecmp (node->name, "itunes:summary") == 0) { description = node->data; } else if (g_ascii_strcasecmp (node->name, "author") == 0 || g_ascii_strcasecmp (node->name, "itunes:author") == 0) { author = node->data; } else if (g_ascii_strcasecmp (node->name, "itunes:duration") == 0) { duration = node->data; } else if (g_ascii_strcasecmp (node->name, "length") == 0) { filesize = node->data; } else if (g_ascii_strcasecmp (node->name, "media:content") == 0) { const char *tmp; tmp = xml_parser_get_property (node, "medium"); if (tmp != NULL && g_str_equal (tmp, "image")) { img = xml_parser_get_property (node, "url"); continue; } tmp = xml_parser_get_property (node, "type"); if (tmp != NULL && g_str_has_prefix (tmp, "audio/") == FALSE) { if (g_str_has_prefix (tmp, "image/")) img = xml_parser_get_property (node, "url"); continue; } content_type = tmp; tmp = xml_parser_get_property (node, "url"); if (tmp != NULL) uri = tmp; else continue; tmp = xml_parser_get_property (node, "fileSize"); if (tmp != NULL) filesize = tmp; tmp = xml_parser_get_property (node, "duration"); if (tmp != NULL) duration = tmp; } else if (g_ascii_strcasecmp (node->name, "enclosure") == 0) { const char *tmp; tmp = xml_parser_get_property (node, "url"); if (tmp != NULL && is_image (tmp) == FALSE) uri = tmp; else continue; tmp = xml_parser_get_property (node, "length"); if (tmp != NULL) filesize = tmp; } else if (g_ascii_strcasecmp (node->name, "link") == 0 && totem_pl_parser_is_videosite (node->data, FALSE) != FALSE) { uri = node->data; } } if (id != NULL && uri == NULL && totem_pl_parser_is_videosite (id, FALSE) != FALSE) uri = id; if (uri != NULL) { totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_URI, uri, TOTEM_PL_PARSER_FIELD_ID, id, TOTEM_PL_PARSER_FIELD_TITLE, title, TOTEM_PL_PARSER_FIELD_PUB_DATE, pub_date, TOTEM_PL_PARSER_FIELD_DESCRIPTION, description, TOTEM_PL_PARSER_FIELD_AUTHOR, author, TOTEM_PL_PARSER_FIELD_DURATION, duration, TOTEM_PL_PARSER_FIELD_FILESIZE, filesize, TOTEM_PL_PARSER_FIELD_CONTENT_TYPE, content_type, TOTEM_PL_PARSER_FIELD_IMAGE_URI, img, NULL); } return TOTEM_PL_PARSER_RESULT_SUCCESS; }
static IdolPlParserResult idol_pl_parser_add_quicktime_metalink (IdolPlParser *parser, GFile *file, GFile *base_file, IdolPlParseData *parse_data, gpointer data) { xml_node_t *doc, *node; gsize size; char *contents; const char *item_uri, *autoplay; gboolean found; if (g_str_has_prefix (data, "RTSPtext") != FALSE || g_str_has_prefix (data, "rtsptext") != FALSE) { return idol_pl_parser_add_quicktime_rtsptext (parser, file, base_file, parse_data, data); } if (g_str_has_prefix (data, "SMILtext") != FALSE) { char *contents; gsize size; IdolPlParserResult retval; if (g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) == FALSE) return IDOL_PL_PARSER_RESULT_ERROR; retval = idol_pl_parser_add_smil_with_data (parser, file, base_file, contents + strlen ("SMILtext"), size - strlen ("SMILtext")); g_free (contents); return retval; } if (g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) == FALSE) return IDOL_PL_PARSER_RESULT_ERROR; doc = idol_pl_parser_parse_xml_relaxed (contents, size); if (doc == NULL) { g_free (contents); return IDOL_PL_PARSER_RESULT_ERROR; } g_free (contents); /* Check for quicktime type */ for (node = doc, found = FALSE; node != NULL; node = node->next) { const char *type; if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name , "?quicktime") != 0) continue; type = xml_parser_get_property (node, "type"); if (g_ascii_strcasecmp ("application/x-quicktime-media-link", type) != 0) continue; found = TRUE; } if (found == FALSE) { xml_parser_free_tree (doc); return IDOL_PL_PARSER_RESULT_ERROR; } if (!doc || !doc->name || g_ascii_strcasecmp (doc->name, "embed") != 0) { xml_parser_free_tree (doc); return IDOL_PL_PARSER_RESULT_ERROR; } item_uri = xml_parser_get_property (doc, "src"); if (!item_uri) { xml_parser_free_tree (doc); return IDOL_PL_PARSER_RESULT_ERROR; } autoplay = xml_parser_get_property (doc, "autoplay"); /* Add a default as per the QuickTime docs */ if (autoplay == NULL) autoplay = "true"; idol_pl_parser_add_uri (parser, IDOL_PL_PARSER_FIELD_URI, item_uri, IDOL_PL_PARSER_FIELD_AUTOPLAY, autoplay, NULL); xml_parser_free_tree (doc); return IDOL_PL_PARSER_RESULT_SUCCESS; }
/* Atom docs: * http://www.atomenabled.org/developers/syndication/atom-format-spec.php#rfc.section.4.1 * http://tools.ietf.org/html/rfc4287 * http://tools.ietf.org/html/rfc4946 */ static IdolPlParserResult parse_atom_entry (IdolPlParser *parser, xml_node_t *parent) { const char *title, *author, *uri, *filesize; const char *copyright, *pub_date, *description; xml_node_t *node; title = author = uri = filesize = NULL; copyright = pub_date = description = NULL; for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "title") == 0) { title = node->data; } else if (g_ascii_strcasecmp (node->name, "author") == 0) { //FIXME } else if (g_ascii_strcasecmp (node->name, "link") == 0) { const char *rel; //FIXME how do we choose the default enclosure type? rel = xml_parser_get_property (node, "rel"); if (g_ascii_strcasecmp (rel, "enclosure") == 0) { const char *href; //FIXME what's the difference between url and href there? href = xml_parser_get_property (node, "href"); if (href == NULL) continue; uri = href; filesize = xml_parser_get_property (node, "length"); } else if (g_ascii_strcasecmp (node->name, "license") == 0) { const char *href; href = xml_parser_get_property (node, "href"); if (href == NULL) continue; /* This isn't really a copyright, but what the hey */ copyright = href; } } else if (g_ascii_strcasecmp (node->name, "updated") == 0 || (g_ascii_strcasecmp (node->name, "modified") == 0 && pub_date == NULL)) { pub_date = node->data; } else if (g_ascii_strcasecmp (node->name, "summary") == 0 || (g_ascii_strcasecmp (node->name, "content") == 0 && description == NULL)) { const char *type; type = xml_parser_get_property (node, "content"); if (type != NULL && g_ascii_strcasecmp (type, "text/plain") == 0) description = node->data; } //FIXME handle category } if (uri != NULL) { idol_pl_parser_add_uri (parser, IDOL_PL_PARSER_FIELD_TITLE, title, IDOL_PL_PARSER_FIELD_AUTHOR, author, IDOL_PL_PARSER_FIELD_URI, uri, IDOL_PL_PARSER_FIELD_FILESIZE, filesize, IDOL_PL_PARSER_FIELD_COPYRIGHT, copyright, IDOL_PL_PARSER_FIELD_PUB_DATE, pub_date, IDOL_PL_PARSER_FIELD_DESCRIPTION, description, NULL); } return IDOL_PL_PARSER_RESULT_SUCCESS; }
static IdolPlParserResult parse_rss_item (IdolPlParser *parser, xml_node_t *parent) { const char *title, *uri, *description, *author; const char *pub_date, *duration, *filesize, *content_type; xml_node_t *node; title = uri = description = author = content_type = NULL; pub_date = duration = filesize = NULL; for (node = parent->child; node != NULL; node = node->next) { if (node->name == NULL) continue; if (g_ascii_strcasecmp (node->name, "title") == 0) { title = node->data; } else if (g_ascii_strcasecmp (node->name, "url") == 0) { uri = node->data; } else if (g_ascii_strcasecmp (node->name, "pubDate") == 0) { pub_date = node->data; } else if (g_ascii_strcasecmp (node->name, "description") == 0 || g_ascii_strcasecmp (node->name, "itunes:summary") == 0) { description = node->data; } else if (g_ascii_strcasecmp (node->name, "author") == 0 || g_ascii_strcasecmp (node->name, "itunes:author") == 0) { author = node->data; } else if (g_ascii_strcasecmp (node->name, "itunes:duration") == 0) { duration = node->data; } else if (g_ascii_strcasecmp (node->name, "length") == 0) { filesize = node->data; } else if (g_ascii_strcasecmp (node->name, "media:content") == 0) { const char *tmp; tmp = xml_parser_get_property (node, "type"); if (tmp != NULL && g_str_has_prefix (tmp, "audio/") == FALSE) continue; content_type = tmp; tmp = xml_parser_get_property (node, "url"); if (tmp != NULL) uri = tmp; else continue; tmp = xml_parser_get_property (node, "fileSize"); if (tmp != NULL) filesize = tmp; tmp = xml_parser_get_property (node, "duration"); if (tmp != NULL) duration = tmp; } else if (g_ascii_strcasecmp (node->name, "enclosure") == 0) { const char *tmp; tmp = xml_parser_get_property (node, "url"); if (tmp != NULL) uri = tmp; else continue; tmp = xml_parser_get_property (node, "length"); if (tmp != NULL) filesize = tmp; } } if (uri != NULL) { idol_pl_parser_add_uri (parser, IDOL_PL_PARSER_FIELD_URI, uri, IDOL_PL_PARSER_FIELD_TITLE, title, IDOL_PL_PARSER_FIELD_PUB_DATE, pub_date, IDOL_PL_PARSER_FIELD_DESCRIPTION, description, IDOL_PL_PARSER_FIELD_AUTHOR, author, IDOL_PL_PARSER_FIELD_DURATION, duration, IDOL_PL_PARSER_FIELD_FILESIZE, filesize, IDOL_PL_PARSER_FIELD_CONTENT_TYPE, content_type, NULL); } return IDOL_PL_PARSER_RESULT_SUCCESS; }