[vlc-commits] demux: playlist: xspf: handle empty elements in current level
Francois Cartegnie
git at videolan.org
Wed Sep 6 13:10:09 CEST 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | 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))
{
More information about the vlc-commits
mailing list