vlc | branch: master | Francois Cartegnie <[email protected]> | Tue Sep 5 17:19:35 2017 +0200| [6d91ece4739ca51b4a52fb6246a0f86aba8f2148] | committer: Francois Cartegnie
demux: playlist: xspf: handle empty elements in current level > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6d91ece4739ca51b4a52fb6246a0f86aba8f2148 --- modules/demux/playlist/xspf.c | 374 +++++++++++++++++++++++------------------- 1 file changed, 207 insertions(+), 167 deletions(-) diff --git a/modules/demux/playlist/xspf.c b/modules/demux/playlist/xspf.c index bf4b4592f5..af15cf16f0 100644 --- a/modules/demux/playlist/xspf.c +++ b/modules/demux/playlist/xspf.c @@ -45,7 +45,8 @@ #define COMPLEX_INTERFACE (stream_t *p_demux,\ input_item_node_t *p_input_node,\ xml_reader_t *p_xml_reader,\ - const char *psz_element) + const char *psz_element,\ + bool b_empty_node) /* prototypes */ static bool parse_playlist_node COMPLEX_INTERFACE; @@ -149,8 +150,11 @@ static int ReadDir(stream_t *p_demux, input_item_node_t *p_subitems) goto end; } + if(xml_ReaderIsEmptyElement(p_xml_reader)) + goto end; + i_ret = parse_playlist_node(p_demux, p_subitems, - p_xml_reader, "playlist") ? 0 : -1; + p_xml_reader, "playlist", false ) ? 0 : -1; for (int i = 0 ; i < sys->i_tracklist_entries ; i++) { @@ -193,6 +197,9 @@ static bool parse_playlist_node COMPLEX_INTERFACE bool b_ret = false; const xml_elem_hnd_t *p_handler = NULL; + if(b_empty_node) + return true; + static const xml_elem_hnd_t pl_elements[] = { {"title", {.smpl = set_item_info}, false }, {"creator", {.smpl = set_item_info}, false }, @@ -235,58 +242,65 @@ static bool parse_playlist_node COMPLEX_INTERFACE psz_value = NULL; while ((i_node = xml_ReaderNextNode(p_xml_reader, &name)) > XML_READER_NONE) - switch (i_node) { - case XML_READER_STARTELEM: - FREENULL(psz_value); - - if (!*name) - { - msg_Err(p_demux, "invalid XML stream"); - goto end; - } - p_handler = get_handler(pl_elements, name); - if (!p_handler) - { - msg_Err(p_demux, "unexpected element <%s>", name); - goto end; - } - /* complex content is parsed in a separate function */ - if (p_handler->cmplx) - { - if (!p_handler->pf_handler.cmplx(p_demux, p_input_node, - p_xml_reader, p_handler->name)) - return false; - p_handler = NULL; - } - break; - - case XML_READER_TEXT: - FREENULL(psz_value); - psz_value = strdup(name); - if (unlikely(!psz_value)) - goto end; - break; - - case XML_READER_ENDELEM: - /* leave if the current parent node <playlist> is terminated */ - if (!strcmp(name, psz_element)) - { - b_ret = true; - goto end; - } - /* there MUST have been a start tag for that element name */ - if (!p_handler || !p_handler->name || strcmp(p_handler->name, name)) + const bool b_empty = xml_ReaderIsEmptyElement(p_xml_reader); + switch (i_node) { - msg_Err(p_demux, "there's no open element left for <%s>", name); - goto end; - } + case XML_READER_STARTELEM: + FREENULL(psz_value); + if (!*name) + { + msg_Err(p_demux, "invalid XML stream"); + goto end; + } + p_handler = get_handler(pl_elements, name); + if (!p_handler) + { + msg_Err(p_demux, "unexpected element <%s>", name); + goto end; + } + + /* complex content is parsed in a separate function */ + if (p_handler->cmplx) + { + if (!p_handler->pf_handler.cmplx(p_demux, p_input_node, + p_xml_reader, p_handler->name, + b_empty)) + return false; + p_handler = NULL; + } + break; + + case XML_READER_TEXT: + FREENULL(psz_value); + if(p_handler) + { + psz_value = strdup(name); + if (unlikely(!psz_value)) + goto end; + } + break; + + case XML_READER_ENDELEM: + /* leave if the current parent node <playlist> is terminated */ + if (!strcmp(name, psz_element)) + { + b_ret = true; + goto end; + } + /* there MUST have been a start tag for that element name */ + if (!p_handler || !p_handler->name || strcmp(p_handler->name, name)) + { + msg_Err(p_demux, "there's no open element left for <%s>", name); + goto end; + } - if (p_handler->pf_handler.smpl) - p_handler->pf_handler.smpl(p_input_item, p_handler->name, psz_value); - FREENULL(psz_value); - p_handler = NULL; - break; + if (p_handler->pf_handler.smpl) + p_handler->pf_handler.smpl(p_input_item, p_handler->name, psz_value); + FREENULL(psz_value); + p_handler = NULL; + break; + } } end: @@ -304,9 +318,13 @@ static bool parse_tracklist_node COMPLEX_INTERFACE unsigned i_ntracks = 0; int i_node; + if(b_empty_node) + return true; + /* now parse the <track>s */ while ((i_node = xml_ReaderNextNode(p_xml_reader, &name)) > XML_READER_NONE) { + const bool b_empty = xml_ReaderIsEmptyElement(p_xml_reader); if (i_node == XML_READER_STARTELEM) { if (strcmp(name, "track")) @@ -317,7 +335,7 @@ static bool parse_tracklist_node COMPLEX_INTERFACE } /* parse the track data in a separate function */ - if (parse_track_node(p_demux, p_input_node, p_xml_reader, "track")) + if (parse_track_node(p_demux, p_input_node, p_xml_reader, "track", b_empty)) i_ntracks++; } else if (i_node == XML_READER_ENDELEM) @@ -353,6 +371,9 @@ static bool parse_track_node COMPLEX_INTERFACE demux_sys_t *p_sys = p_demux->p_sys; int i_node; + if(b_empty_node) + return true; + static const xml_elem_hnd_t track_elements[] = { {"location", {NULL}, false }, {"identifier", {NULL}, false }, @@ -378,129 +399,136 @@ static bool parse_track_node COMPLEX_INTERFACE p_sys->i_track_id = -1; while ((i_node = xml_ReaderNextNode(p_xml_reader, &name)) > XML_READER_NONE) - switch (i_node) { - case XML_READER_STARTELEM: - FREENULL(psz_value); - - if (!*name) - { - msg_Err(p_demux, "invalid XML stream"); - goto end; - } - p_handler = get_handler(track_elements, name); - if (!p_handler) - { - msg_Err(p_demux, "unexpected element <%s>", name); - goto end; - } - /* complex content is parsed in a separate function */ - if (p_handler->cmplx) - { - if (!p_handler->pf_handler.cmplx(p_demux, p_new_node, - p_xml_reader, p_handler->name)) { - input_item_node_Delete(p_new_node); - input_item_Release(p_new_input); - return false; - } - - p_handler = NULL; - } - break; - - case XML_READER_TEXT: - free(psz_value); - psz_value = strdup(name); - if (unlikely(!psz_value)) - goto end; - break; - - case XML_READER_ENDELEM: - /* leave if the current parent node <track> is terminated */ - if (!strcmp(name, psz_element)) + const bool b_empty = xml_ReaderIsEmptyElement(p_xml_reader); + switch (i_node) { - free(psz_value); + case XML_READER_STARTELEM: + FREENULL(psz_value); - /* Make sure we have a URI */ - char *psz_uri = input_item_GetURI(p_new_input); - if (!psz_uri) - input_item_SetURI(p_new_input, "vlc://nop"); - else - free(psz_uri); + if (!*name) + { + msg_Err(p_demux, "invalid XML stream"); + goto end; + } + p_handler = get_handler(track_elements, name); + if (!p_handler) + { + msg_Err(p_demux, "unexpected element <%s>", name); + goto end; + } + /* complex content is parsed in a separate function */ + if (p_handler->cmplx) + { + if (!p_handler->pf_handler.cmplx(p_demux, p_new_node, + p_xml_reader, p_handler->name, + b_empty)) { + input_item_node_Delete(p_new_node); + input_item_Release(p_new_input); + return false; + } - if (p_sys->i_track_id < 0 - || (size_t)p_sys->i_track_id >= (SIZE_MAX / sizeof(p_new_input))) - { - input_item_node_AppendNode(p_input_node, p_new_node); - input_item_Release(p_new_input); - return true; - } + p_handler = NULL; + } + break; - if (p_sys->i_track_id >= p_sys->i_tracklist_entries) - { - input_item_t **pp; - pp = realloc(p_sys->pp_tracklist, - (p_sys->i_track_id + 1) * sizeof(*pp)); - if (!pp) + case XML_READER_TEXT: + FREENULL(psz_value); + if(p_handler) { - input_item_Release(p_new_input); - input_item_node_Delete(p_new_node); - return false; + psz_value = strdup(name); + if (unlikely(!psz_value)) + goto end; } - p_sys->pp_tracklist = pp; - while (p_sys->i_track_id >= p_sys->i_tracklist_entries) - pp[p_sys->i_tracklist_entries++] = NULL; - } - else if (p_sys->pp_tracklist[p_sys->i_track_id] != NULL) - { - msg_Err(p_demux, "track ID %d collision", p_sys->i_track_id); - input_item_Release(p_new_input); - input_item_node_Delete(p_new_node); - return false; - } + break; - p_sys->pp_tracklist[ p_sys->i_track_id ] = p_new_input; - input_item_node_Delete(p_new_node); - return true; - } - /* there MUST have been a start tag for that element name */ - if (!p_handler || !p_handler->name || strcmp(p_handler->name, name)) - { - msg_Err(p_demux, "there's no open element left for <%s>", name); - goto end; - } + case XML_READER_ENDELEM: + /* leave if the current parent node <track> is terminated */ + if (!strcmp(name, psz_element)) + { + free(psz_value); - /* special case: location */ - if (!strcmp(p_handler->name, "location")) - { - if (psz_value == NULL) - input_item_SetURI(p_new_input, "vlc://nop"); - else - { - char* psz_uri = ProcessMRL( psz_value, p_sys->psz_base ); + /* Make sure we have a URI */ + char *psz_uri = input_item_GetURI(p_new_input); + if (!psz_uri) + input_item_SetURI(p_new_input, "vlc://nop"); + else + free(psz_uri); - if( !psz_uri ) + if (p_sys->i_track_id < 0 + || (size_t)p_sys->i_track_id >= (SIZE_MAX / sizeof(p_new_input))) + { + input_item_node_AppendNode(p_input_node, p_new_node); + input_item_Release(p_new_input); + return true; + } + + if (p_sys->i_track_id >= p_sys->i_tracklist_entries) + { + input_item_t **pp; + pp = realloc(p_sys->pp_tracklist, + (p_sys->i_track_id + 1) * sizeof(*pp)); + if (!pp) + { + input_item_Release(p_new_input); + input_item_node_Delete(p_new_node); + return false; + } + p_sys->pp_tracklist = pp; + while (p_sys->i_track_id >= p_sys->i_tracklist_entries) + pp[p_sys->i_tracklist_entries++] = NULL; + } + else if (p_sys->pp_tracklist[p_sys->i_track_id] != NULL) + { + msg_Err(p_demux, "track ID %d collision", p_sys->i_track_id); + input_item_Release(p_new_input); + input_item_node_Delete(p_new_node); + return false; + } + + p_sys->pp_tracklist[ p_sys->i_track_id ] = p_new_input; + input_item_node_Delete(p_new_node); + return true; + } + /* there MUST have been a start tag for that element name */ + if (!p_handler || !p_handler->name || strcmp(p_handler->name, name)) { - msg_Warn( p_demux, "unable to process MRL: %s", psz_value ); + msg_Err(p_demux, "there's no open element left for <%s>", name); goto end; } - input_item_SetURI(p_new_input, psz_uri); - free(psz_uri); - } + /* special case: location */ + if (!strcmp(p_handler->name, "location")) + { + if (psz_value == NULL) + input_item_SetURI(p_new_input, "vlc://nop"); + else + { + char* psz_uri = ProcessMRL( psz_value, p_sys->psz_base ); - input_item_CopyOptions(p_new_input, p_input_item); - } - else - { - /* there MUST be an item */ - if (p_handler->pf_handler.smpl) - p_handler->pf_handler.smpl(p_new_input, p_handler->name, - psz_value); + if( !psz_uri ) + { + msg_Warn( p_demux, "unable to process MRL: %s", psz_value ); + goto end; + } + + input_item_SetURI(p_new_input, psz_uri); + free(psz_uri); + } + + input_item_CopyOptions(p_new_input, p_input_item); + } + else + { + /* there MUST be an item */ + if (p_handler->pf_handler.smpl) + p_handler->pf_handler.smpl(p_new_input, p_handler->name, + psz_value); + } + FREENULL(psz_value); + p_handler = NULL; + break; } - FREENULL(psz_value); - p_handler = NULL; - break; } msg_Err(p_demux, "unexpected end of xml data"); @@ -573,6 +601,9 @@ static bool parse_extension_node COMPLEX_INTERFACE const xml_elem_hnd_t *p_handler = NULL; input_item_t *p_new_input = NULL; + if(b_empty_node) + return true; + static const xml_elem_hnd_t pl_elements[] = { {"vlc:node", {.cmplx = parse_extension_node}, true }, {"vlc:item", {.cmplx = parse_extitem_node}, true }, @@ -630,7 +661,7 @@ static bool parse_extension_node COMPLEX_INTERFACE else if (strcmp(psz_application, "http://www.videolan.org/vlc/playlist/0")) { msg_Dbg(p_demux, "Skipping \"%s\" extension tag", psz_application); - skip_element( NULL, NULL, p_xml_reader, NULL ); + skip_element( NULL, NULL, p_xml_reader, NULL, b_empty_node ); goto success; } } @@ -638,6 +669,7 @@ static bool parse_extension_node COMPLEX_INTERFACE /* parse the child elements */ while ((i_node = xml_ReaderNextNode(p_xml_reader, &name)) > XML_READER_NONE) { + const bool b_empty = xml_ReaderIsEmptyElement(p_xml_reader); switch (i_node) { case XML_READER_STARTELEM: @@ -657,10 +689,9 @@ static bool parse_extension_node COMPLEX_INTERFACE /* complex content is parsed in a separate function */ if (p_handler->cmplx) { - if (p_handler->pf_handler.cmplx(p_demux, - p_input_node, - p_xml_reader, - p_handler->name)) + if (p_handler->pf_handler.cmplx(p_demux, p_input_node, + p_xml_reader, p_handler->name, + b_empty)) { p_handler = NULL; } @@ -671,9 +702,12 @@ static bool parse_extension_node COMPLEX_INTERFACE case XML_READER_TEXT: FREENULL(psz_value); - psz_value = strdup(name); - if (unlikely(!psz_value)) - goto error; + if(p_handler) + { + psz_value = strdup(name); + if (unlikely(!psz_value)) + goto error; + } break; case XML_READER_ENDELEM: @@ -730,6 +764,9 @@ static bool parse_extitem_node COMPLEX_INTERFACE input_item_t *p_new_input = NULL; int i_tid = -1; + if(!b_empty_node) + return false; + /* read all extension item attributes */ const char *name, *value; while ((name = xml_ReaderNextAttr(p_xml_reader, &value)) != NULL) @@ -774,6 +811,9 @@ static bool skip_element COMPLEX_INTERFACE VLC_UNUSED(p_demux); VLC_UNUSED(p_input_node); VLC_UNUSED(psz_element); + if(b_empty_node) + return true; + for (unsigned lvl = 1; lvl;) switch (xml_ReaderNextNode(p_xml_reader, NULL)) { _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
