/* <genrelist> * <genre name="the name"></genre> * ... * </genrelist> **/ static int DemuxGenre( demux_t *p_demux, xml_reader_t *p_xml_reader, input_item_node_t *p_input_node ) { const char *node; char *psz_name = NULL; /* genre name */ int type; while( (type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( type ) { case XML_READER_STARTELEM: { if( !strcmp( node, "genre" ) ) { // Read the attributes const char *name, *value; while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( name, "name" ) ) { free(psz_name); psz_name = strdup( value ); } else msg_Warn( p_demux, "unexpected attribute %s in <%s>", name, node ); } } break; } case XML_READER_ENDELEM: if( !strcmp( node, "genre" ) && psz_name != NULL ) { char* psz_mrl; if( asprintf( &psz_mrl, SHOUTCAST_BASE_URL "?genre=%s", psz_name ) != -1 ) { input_item_t *p_input; vlc_xml_decode( psz_mrl ); p_input = input_item_New( psz_mrl, psz_name ); input_item_CopyOptions( p_input_node->p_item, p_input ); free( psz_mrl ); input_item_node_AppendItem( p_input_node, p_input ); vlc_gc_decref( p_input ); } FREENULL( psz_name ); } break; } } free( psz_name ); return 0; }
static void decode (const char *in, const char *out) { char buf[strlen (in) + 1]; printf ("\"%s\" -> \"%s\" ?\n", in, out); strcpy (buf, in); vlc_xml_decode (buf); if (strcmp (buf, out)) { printf (" ERROR: got \"%s\"\n", buf); exit (2); } }
static void ReadElement( xml_reader_t *p_xml_reader, char **ppsz_txt ) { const char *psz_node = NULL; /* Read the text node */ xml_ReaderNextNode( p_xml_reader, &psz_node ); free( *ppsz_txt ); *ppsz_txt = strdup( psz_node ); vlc_xml_decode( *ppsz_txt ); /* Read the end element */ xml_ReaderNextNode( p_xml_reader, &psz_node ); /* TODO : * Currently we don't check the agreement of start and end element * This function is only used to read the element that cannot have child * according to the reference. */ }
/* "specs" : http://phobos.apple.com/static/iTunesRSS.html */ static int ReadDir( stream_t *p_demux, input_item_node_t *p_subitems ) { bool b_item = false; bool b_image = false; xml_reader_t *p_xml_reader; char *psz_elname = NULL; char *psz_item_mrl = NULL; char *psz_item_size = NULL; char *psz_item_type = NULL; char *psz_item_name = NULL; char *psz_item_date = NULL; char *psz_item_author = NULL; char *psz_item_category = NULL; char *psz_item_duration = NULL; char *psz_item_keywords = NULL; char *psz_item_subtitle = NULL; char *psz_item_summary = NULL; char *psz_art_url = NULL; const char *node; int i_type; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) goto error; /* xml */ /* check root node */ if( xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "invalid file (no root node)" ); goto error; } if( strcmp( node, "rss" ) ) { msg_Err( p_demux, "invalid root node <%s>", node ); goto error; } while( (i_type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( i_type ) { case XML_READER_STARTELEM: { free( psz_elname ); psz_elname = strdup( node ); if( unlikely(!psz_elname) ) goto error; if( !strcmp( node, "item" ) ) b_item = true; else if( !strcmp( node, "image" ) ) b_image = true; // Read the attributes const char *attr, *value; while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( node, "enclosure" ) ) { char **p = NULL; if( !strcmp( attr, "url" ) ) p = &psz_item_mrl; else if( !strcmp( attr, "length" ) ) p = &psz_item_size; else if( !strcmp( attr, "type" ) ) p = &psz_item_type; if( p != NULL ) { free( *p ); *p = strdup( value ); } else msg_Dbg( p_demux,"unhandled attribute %s in <%s>", attr, node ); } else msg_Dbg( p_demux,"unhandled attribute %s in <%s>", attr, node ); } break; } case XML_READER_TEXT: { if(!psz_elname) break; /* item specific meta data */ if( b_item ) { char **p; if( !strcmp( psz_elname, "title" ) ) p = &psz_item_name; else if( !strcmp( psz_elname, "itunes:author" ) || !strcmp( psz_elname, "author" ) ) /* <author> isn't standard iTunes podcast stuff */ p = &psz_item_author; else if( !strcmp( psz_elname, "itunes:summary" ) || !strcmp( psz_elname, "description" ) ) /* <description> isn't standard iTunes podcast stuff */ p = &psz_item_summary; else if( !strcmp( psz_elname, "pubDate" ) ) p = &psz_item_date; else if( !strcmp( psz_elname, "itunes:category" ) ) p = &psz_item_category; else if( !strcmp( psz_elname, "itunes:duration" ) ) p = &psz_item_duration; else if( !strcmp( psz_elname, "itunes:keywords" ) ) p = &psz_item_keywords; else if( !strcmp( psz_elname, "itunes:subtitle" ) ) p = &psz_item_subtitle; else break; free( *p ); *p = strdup( node ); } /* toplevel meta data */ else if( !b_image ) { if( !strcmp( psz_elname, "title" ) ) input_item_SetName( p_current_input, node ); #define ADD_GINFO( info, name ) \ else if( !strcmp( psz_elname, name ) ) \ input_item_AddInfo( p_current_input, _("Podcast Info"), \ info, "%s", node ); ADD_GINFO( _("Podcast Link"), "link" ) ADD_GINFO( _("Podcast Copyright"), "copyright" ) ADD_GINFO( _("Podcast Category"), "itunes:category" ) ADD_GINFO( _("Podcast Keywords"), "itunes:keywords" ) ADD_GINFO( _("Podcast Subtitle"), "itunes:subtitle" ) #undef ADD_GINFO else if( !strcmp( psz_elname, "itunes:summary" ) || !strcmp( psz_elname, "description" ) ) { /* <description> isn't standard iTunes podcast stuff */ input_item_AddInfo( p_current_input, _( "Podcast Info" ), _( "Podcast Summary" ), "%s", node ); } } else { if( !strcmp( psz_elname, "url" ) && *node ) { free( psz_art_url ); psz_art_url = strdup( node ); } else msg_Dbg( p_demux, "unhandled text in element <%s>", psz_elname ); } break; } // End element case XML_READER_ENDELEM: { FREENULL( psz_elname ); if( !strcmp( node, "item" ) ) { if( psz_item_mrl == NULL ) { if (psz_item_name) msg_Warn( p_demux, "invalid XML item, skipping %s", psz_item_name ); else msg_Warn( p_demux, "invalid XML item, skipped" ); FREENULL( psz_item_name ); FREENULL( psz_item_size ); FREENULL( psz_item_type ); FREENULL( psz_item_date ); FREENULL( psz_item_author ); FREENULL( psz_item_category ); FREENULL( psz_item_duration ); FREENULL( psz_item_keywords ); FREENULL( psz_item_subtitle ); FREENULL( psz_item_summary ); FREENULL( psz_art_url ); FREENULL( psz_elname ); continue; } vlc_xml_decode( psz_item_mrl ); vlc_xml_decode( psz_item_name ); p_input = input_item_New( psz_item_mrl, psz_item_name ); FREENULL( psz_item_mrl ); FREENULL( psz_item_name ); if( p_input == NULL ) break; /* FIXME: meta data memory leaks? */ /* Set the duration if available */ if( psz_item_duration ) p_input->i_duration = strTimeToMTime( psz_item_duration ); #define ADD_INFO( info, field ) \ if( field ) { \ input_item_AddInfo( p_input, _( "Podcast Info" ), (info), "%s", \ (field) ); \ FREENULL( field ); } ADD_INFO( _("Podcast Publication Date"), psz_item_date ); ADD_INFO( _("Podcast Author"), psz_item_author ); ADD_INFO( _("Podcast Subcategory"), psz_item_category ); ADD_INFO( _("Podcast Duration"), psz_item_duration ); ADD_INFO( _("Podcast Keywords"), psz_item_keywords ); ADD_INFO( _("Podcast Subtitle"), psz_item_subtitle ); ADD_INFO( _("Podcast Summary"), psz_item_summary ); ADD_INFO( _("Podcast Type"), psz_item_type ); #undef ADD_INFO /* Add the global art url to this item, if any */ if( psz_art_url ) { vlc_xml_decode( psz_art_url ); input_item_SetArtURL( p_input, psz_art_url ); } if( psz_item_size ) { input_item_AddInfo( p_input, _( "Podcast Info" ), _( "Podcast Size" ), _("%s bytes"), psz_item_size ); FREENULL( psz_item_size ); } input_item_node_AppendItem( p_subitems, p_input ); input_item_Release( p_input ); b_item = false; } else if( !strcmp( node, "image" ) ) { b_image = false; } break; } } }
static int ReadDir( stream_t *p_demux, input_item_node_t *p_subitems ) { xml_reader_t *p_xml_reader; input_item_t *p_input; int i_ret = -1; /* List of all possible attributes. The only required one is "src" */ bool b_autoplay = false; bool b_controller = true; qtl_fullscreen_t fullscreen = false; char *psz_href = NULL; bool b_kioskmode = false; qtl_loop_t loop = LOOP_FALSE; int i_movieid = -1; char *psz_moviename = NULL; bool b_playeveryframe = false; char *psz_qtnext = NULL; bool b_quitwhendone = false; char *psz_src = NULL; char *psz_mimetype = NULL; int i_volume = 100; p_xml_reader = xml_ReaderCreate( p_demux, p_demux->p_source ); if( !p_xml_reader ) goto error; for( int i = 0;; ++i ) /* locate root node */ { const char *node; if( i == ROOT_NODE_MAX_DEPTH || xml_ReaderNextNode( p_xml_reader, &node ) != XML_READER_STARTELEM ) { msg_Err( p_demux, "unable to locate root-node" ); goto error; } if( strcmp( node, "embed" ) == 0 ) break; /* found it */ msg_Dbg( p_demux, "invalid root node <%s>, trying next (%d / %d)", node, i + 1, ROOT_NODE_MAX_DEPTH ); } const char *attrname, *value; while( (attrname = xml_ReaderNextAttr( p_xml_reader, &value )) != NULL ) { if( !strcmp( attrname, "autoplay" ) ) b_autoplay = !strcmp( value, "true" ); else if( !strcmp( attrname, "controller" ) ) b_controller = !strcmp( attrname, "false" ); else if( !strcmp( attrname, "fullscreen" ) ) { if( !strcmp( value, "double" ) ) fullscreen = FULLSCREEN_DOUBLE; else if( !strcmp( value, "half" ) ) fullscreen = FULLSCREEN_HALF; else if( !strcmp( value, "current" ) ) fullscreen = FULLSCREEN_CURRENT; else if( !strcmp( value, "full" ) ) fullscreen = FULLSCREEN_FULL; else fullscreen = FULLSCREEN_NORMAL; } else if( !strcmp( attrname, "href" ) ) { free( psz_href ); psz_href = strdup( value ); } else if( !strcmp( attrname, "kioskmode" ) ) b_kioskmode = !strcmp( value, "true" ); else if( !strcmp( attrname, "loop" ) ) { if( !strcmp( value, "true" ) ) loop = LOOP_TRUE; else if( !strcmp( value, "palindrome" ) ) loop = LOOP_PALINDROME; else loop = LOOP_FALSE; } else if( !strcmp( attrname, "movieid" ) ) i_movieid = atoi( value ); else if( !strcmp( attrname, "moviename" ) ) { free( psz_moviename ); psz_moviename = strdup( value ); } else if( !strcmp( attrname, "playeveryframe" ) ) b_playeveryframe = !strcmp( value, "true" ); else if( !strcmp( attrname, "qtnext" ) ) { free( psz_qtnext ); psz_qtnext = strdup( value ); } else if( !strcmp( attrname, "quitwhendone" ) ) b_quitwhendone = !strcmp( value, "true" ); else if( !strcmp( attrname, "src" ) ) { free( psz_src ); psz_src = strdup( value ); } else if( !strcmp( attrname, "mimetype" ) ) { free( psz_mimetype ); psz_mimetype = strdup( value ); } else if( !strcmp( attrname, "volume" ) ) i_volume = atoi( value ); else msg_Dbg( p_demux, "Attribute %s with value %s isn't valid", attrname, value ); } msg_Dbg( p_demux, "autoplay: %s (unused by VLC)", b_autoplay ? "true": "false" ); msg_Dbg( p_demux, "controller: %s (unused by VLC)", b_controller ? "true": "false" ); msg_Dbg( p_demux, "fullscreen: %s (unused by VLC)", ppsz_fullscreen[fullscreen] ); msg_Dbg( p_demux, "href: %s", psz_href ); msg_Dbg( p_demux, "kioskmode: %s (unused by VLC)", b_kioskmode ? "true":"false" ); msg_Dbg( p_demux, "loop: %s (unused by VLC)", ppsz_loop[loop] ); msg_Dbg( p_demux, "movieid: %d (unused by VLC)", i_movieid ); msg_Dbg( p_demux, "moviename: %s", psz_moviename ); msg_Dbg( p_demux, "playeverframe: %s (unused by VLC)", b_playeveryframe ? "true":"false" ); msg_Dbg( p_demux, "qtnext: %s", psz_qtnext ); msg_Dbg( p_demux, "quitwhendone: %s (unused by VLC)", b_quitwhendone ? "true":"false" ); msg_Dbg( p_demux, "src: %s", psz_src ); msg_Dbg( p_demux, "mimetype: %s", psz_mimetype ); msg_Dbg( p_demux, "volume: %d (unused by VLC)", i_volume ); if( !psz_src ) { msg_Err( p_demux, "Mandatory attribute 'src' not found" ); } else { p_input = input_item_New( psz_src, psz_moviename ); #define SADD_INFO( type, field ) if( field ) { input_item_AddInfo( \ p_input, "QuickTime Media Link", type, "%s", field ) ; } SADD_INFO( "href", psz_href ); SADD_INFO( _("Mime"), psz_mimetype ); input_item_node_AppendItem( p_subitems, p_input ); input_item_Release( p_input ); if( psz_qtnext ) { vlc_xml_decode( psz_qtnext ); p_input = input_item_New( psz_qtnext, NULL ); input_item_node_AppendItem( p_subitems, p_input ); input_item_Release( p_input ); } } i_ret = 0; /* Needed for correct operation of go back */ error: if( p_xml_reader ) xml_ReaderDelete( p_xml_reader ); free( psz_href ); free( psz_moviename ); free( psz_qtnext ); free( psz_src ); free( psz_mimetype ); return i_ret; }
/***************************************************************************** * Connect: *****************************************************************************/ static int Connect( stream_t *p_access ) { access_sys_t *p_sys = p_access->p_sys; vlc_url_t srv = p_sys->b_proxy ? p_sys->proxy : p_sys->url; ssize_t val; /* Clean info */ free( p_sys->psz_location ); free( p_sys->psz_mime ); free( p_sys->psz_icy_genre ); free( p_sys->psz_icy_name ); free( p_sys->psz_icy_title ); vlc_http_auth_Init( &p_sys->auth ); vlc_http_auth_Init( &p_sys->proxy_auth ); p_sys->psz_location = NULL; p_sys->psz_mime = NULL; p_sys->i_icy_meta = 0; p_sys->i_icy_offset = 0; p_sys->psz_icy_name = NULL; p_sys->psz_icy_genre = NULL; p_sys->psz_icy_title = NULL; p_sys->b_has_size = false; p_sys->offset = 0; p_sys->size = 0; struct vlc_memstream stream; vlc_memstream_open(&stream); vlc_memstream_puts(&stream, "GET "); if( p_sys->b_proxy ) vlc_memstream_printf( &stream, "http://%s:%d", p_sys->url.psz_host, p_sys->url.i_port ); if( p_sys->url.psz_path == NULL || p_sys->url.psz_path[0] == '\0' ) vlc_memstream_putc( &stream, '/' ); else vlc_memstream_puts( &stream, p_sys->url.psz_path ); if( p_sys->url.psz_option != NULL ) vlc_memstream_printf( &stream, "?%s", p_sys->url.psz_option ); vlc_memstream_puts( &stream, " HTTP/1.0\r\n" ); vlc_memstream_printf( &stream, "Host: %s", p_sys->url.psz_host ); if( p_sys->url.i_port != 80 ) vlc_memstream_printf( &stream, ":%d", p_sys->url.i_port ); vlc_memstream_puts( &stream, "\r\n" ); /* User Agent */ vlc_memstream_printf( &stream, "User-Agent: %s\r\n", p_sys->psz_user_agent ); /* Referrer */ if (p_sys->psz_referrer) vlc_memstream_printf( &stream, "Referer: %s\r\n", p_sys->psz_referrer ); /* Authentication */ if( p_sys->url.psz_username != NULL && p_sys->url.psz_password != NULL ) { char *auth; auth = vlc_http_auth_FormatAuthorizationHeader( VLC_OBJECT(p_access), &p_sys->auth, "GET", p_sys->url.psz_path, p_sys->url.psz_username, p_sys->url.psz_password ); if( auth != NULL ) vlc_memstream_printf( &stream, "Authorization: %s\r\n", auth ); free( auth ); } /* Proxy Authentication */ if( p_sys->b_proxy && p_sys->proxy.psz_username != NULL && p_sys->proxy.psz_password != NULL ) { char *auth; auth = vlc_http_auth_FormatAuthorizationHeader( VLC_OBJECT(p_access), &p_sys->proxy_auth, "GET", p_sys->url.psz_path, p_sys->proxy.psz_username, p_sys->proxy.psz_password ); if( auth != NULL ) vlc_memstream_printf( &stream, "Proxy-Authorization: %s\r\n", auth ); free( auth ); } /* ICY meta data request */ vlc_memstream_puts( &stream, "Icy-MetaData: 1\r\n" ); vlc_memstream_puts( &stream, "\r\n" ); if( vlc_memstream_close( &stream ) ) return -1; /* Open connection */ assert(p_sys->stream == NULL); /* No open sockets (leaking fds is BAD) */ p_sys->stream = vlc_tls_SocketOpenTCP(VLC_OBJECT(p_access), srv.psz_host, srv.i_port); if (p_sys->stream == NULL) { msg_Err( p_access, "cannot connect to %s:%d", srv.psz_host, srv.i_port ); free( stream.ptr ); return -1; } msg_Dbg( p_access, "sending request:\n%s", stream.ptr ); val = vlc_tls_Write(p_sys->stream, stream.ptr, stream.length); free( stream.ptr ); if( val < (ssize_t)stream.length ) { msg_Err( p_access, "failed to send request" ); Disconnect( p_access ); return -2; } /* Read Answer */ char *psz = vlc_tls_GetLine(p_sys->stream); if( psz == NULL ) { msg_Err( p_access, "failed to read answer" ); goto error; } if( !strncmp( psz, "HTTP/1.", 7 ) ) { p_sys->i_code = atoi( &psz[9] ); msg_Dbg( p_access, "HTTP answer code %d", p_sys->i_code ); } else if( !strncmp( psz, "ICY", 3 ) ) { p_sys->i_code = atoi( &psz[4] ); msg_Dbg( p_access, "ICY answer code %d", p_sys->i_code ); p_sys->b_icecast = true; p_sys->b_reconnect = true; } else { msg_Err( p_access, "invalid HTTP reply '%s'", psz ); free( psz ); goto error; } /* Authentication error - We'll have to display the dialog */ if( p_sys->i_code == 401 ) { } /* Other fatal error */ else if( p_sys->i_code >= 400 ) { msg_Err( p_access, "error: %s", psz ); free( psz ); goto error; } free( psz ); for( ;; ) { char *p, *p_trailing; psz = vlc_tls_GetLine(p_sys->stream); if( psz == NULL ) { msg_Err( p_access, "failed to read answer" ); goto error; } /* msg_Dbg( p_input, "Line=%s", psz ); */ if( *psz == '\0' ) { free( psz ); break; } if( ( p = strchr( psz, ':' ) ) == NULL ) { msg_Err( p_access, "malformed header line: %s", psz ); free( psz ); goto error; } *p++ = '\0'; p += strspn( p, " \t" ); /* trim trailing white space */ p_trailing = p + strlen( p ); if( p_trailing > p ) { p_trailing--; while( ( *p_trailing == ' ' || *p_trailing == '\t' ) && p_trailing > p ) { *p_trailing = '\0'; p_trailing--; } } if( !strcasecmp( psz, "Content-Length" ) ) { uint64_t i_size = (uint64_t)atoll( p ); if(i_size > p_sys->size) { p_sys->b_has_size = true; p_sys->size = i_size; } } else if( !strcasecmp( psz, "Location" ) ) { char * psz_new_loc; /* This does not follow RFC 2068, but yet if the url is not absolute, * handle it as everyone does. */ if( p[0] == '/' ) { if( p_sys->url.i_port == 80 ) { if( asprintf(&psz_new_loc, "http://%s%s", p_sys->url.psz_host, p) < 0 ) goto error; } else { if( asprintf(&psz_new_loc, "http://%s:%d%s", p_sys->url.psz_host, p_sys->url.i_port, p) < 0 ) goto error; } } else { psz_new_loc = strdup( p ); } free( p_sys->psz_location ); p_sys->psz_location = psz_new_loc; } else if( !strcasecmp( psz, "Content-Type" ) ) { free( p_sys->psz_mime ); p_sys->psz_mime = strdup( p ); msg_Dbg( p_access, "Content-Type: %s", p_sys->psz_mime ); } else if( !strcasecmp( psz, "Content-Encoding" ) ) { msg_Dbg( p_access, "Content-Encoding: %s", p ); } else if( !strcasecmp( psz, "Server" ) ) { msg_Dbg( p_access, "Server: %s", p ); if( !strncasecmp( p, "Icecast", 7 ) || !strncasecmp( p, "Nanocaster", 10 ) ) { /* Remember if this is Icecast * we need to force demux in this case without breaking * autodetection */ /* Let live 365 streams (nanocaster) piggyback on the icecast * routine. They look very similar */ p_sys->b_reconnect = true; p_sys->b_icecast = true; } } else if( !strcasecmp( psz, "Icy-MetaInt" ) ) { msg_Dbg( p_access, "Icy-MetaInt: %s", p ); p_sys->i_icy_meta = atoi( p ); if( p_sys->i_icy_meta < 0 ) p_sys->i_icy_meta = 0; if( p_sys->i_icy_meta > 1 ) { p_sys->i_icy_offset = p_sys->i_icy_meta; p_sys->b_icecast = true; } msg_Warn( p_access, "ICY metaint=%d", p_sys->i_icy_meta ); } else if( !strcasecmp( psz, "Icy-Name" ) ) { free( p_sys->psz_icy_name ); char *psz_tmp = strdup( p ); p_sys->psz_icy_name = EnsureUTF8( psz_tmp ); if( !p_sys->psz_icy_name ) free( psz_tmp ); else vlc_xml_decode( p_sys->psz_icy_name ); msg_Dbg( p_access, "Icy-Name: %s", p_sys->psz_icy_name ); if ( p_access->p_input_item ) input_item_SetMeta( p_access->p_input_item, vlc_meta_Title, p_sys->psz_icy_name ); p_sys->b_icecast = true; /* be on the safeside. set it here as well. */ p_sys->b_reconnect = true; } else if( !strcasecmp( psz, "Icy-Genre" ) ) { free( p_sys->psz_icy_genre ); char *psz_tmp = strdup( p ); p_sys->psz_icy_genre = EnsureUTF8( psz_tmp ); if( !p_sys->psz_icy_genre ) free( psz_tmp ); else vlc_xml_decode( p_sys->psz_icy_genre ); msg_Dbg( p_access, "Icy-Genre: %s", p_sys->psz_icy_genre ); if( p_access->p_input_item ) input_item_SetMeta( p_access->p_input_item, vlc_meta_Genre, p_sys->psz_icy_genre ); } else if( !strncasecmp( psz, "Icy-Notice", 10 ) ) { msg_Dbg( p_access, "Icy-Notice: %s", p ); } else if( !strncasecmp( psz, "icy-", 4 ) || !strncasecmp( psz, "ice-", 4 ) || !strncasecmp( psz, "x-audiocast", 11 ) ) { msg_Dbg( p_access, "Meta-Info: %s: %s", psz, p ); } else if( !strcasecmp( psz, "www-authenticate" ) ) { msg_Dbg( p_access, "Authentication header: %s", p ); vlc_http_auth_ParseWwwAuthenticateHeader( VLC_OBJECT(p_access), &p_sys->auth, p ); } else if( !strcasecmp( psz, "proxy-authenticate" ) ) { msg_Dbg( p_access, "Proxy authentication header: %s", p ); vlc_http_auth_ParseWwwAuthenticateHeader( VLC_OBJECT(p_access), &p_sys->proxy_auth, p ); } else if( !strcasecmp( psz, "authentication-info" ) ) { msg_Dbg( p_access, "Authentication Info header: %s", p ); if( AuthCheckReply( p_access, p, &p_sys->url, &p_sys->auth ) ) goto error; } else if( !strcasecmp( psz, "proxy-authentication-info" ) ) { msg_Dbg( p_access, "Proxy Authentication Info header: %s", p ); if( AuthCheckReply( p_access, p, &p_sys->proxy, &p_sys->proxy_auth ) ) goto error; } free( psz ); } return 0; error: Disconnect( p_access ); return -2; }
static int Demux( demux_t *p_demux ) { const char *psz_node = NULL; char *psz_txt = NULL; char *psz_base = FindPrefix( p_demux ); char *psz_title_asx = NULL; char *psz_entryref = NULL; xml_reader_t *p_xml_reader = NULL; input_item_t *p_current_input = GetCurrentItem( p_demux ); input_item_node_t *p_subitems = NULL; bool b_first_node = false; int i_type; int i_n_entry = 0; p_xml_reader = xml_ReaderCreate( p_demux, p_demux->s ); if( !p_xml_reader ) { msg_Err( p_demux, "Cannot parse ASX input file as XML"); goto error; } p_subitems = input_item_node_Create( p_current_input ); do { i_type = xml_ReaderNextNode( p_xml_reader, &psz_node ); if( i_type == XML_READER_STARTELEM ) { if( !b_first_node ) { if(!strncasecmp( psz_node, "ASX", 3 ) ) b_first_node = true; else { msg_Err( p_demux, "invalid root node" ); goto error; } } /* Metadata Node Handler */ if( !strncasecmp( psz_node, "TITLE", 5 ) ) { ReadElement( p_xml_reader, &psz_title_asx ); input_item_SetTitle( p_current_input, psz_title_asx ); } else if( !strncasecmp( psz_node, "AUTHOR", 6 ) ) { ReadElement( p_xml_reader, &psz_txt ); input_item_SetArtist( p_current_input, psz_txt ); } else if( !strncasecmp( psz_node, "COPYRIGHT", 9 ) ) { ReadElement( p_xml_reader, &psz_txt ); input_item_SetCopyright( p_current_input, psz_txt ); } else if( !strncasecmp( psz_node, "MOREINFO", 8 ) ) { const char *psz_tmp; do { psz_tmp = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while( psz_tmp && strncasecmp( psz_tmp, "HREF", 4 ) ); if( !psz_tmp ) // If HREF attribute doesn't exist ReadElement( p_xml_reader, &psz_txt ); else psz_txt = strdup( psz_node ); vlc_xml_decode( psz_txt ); input_item_SetURL( p_current_input, psz_txt ); } else if( !strncasecmp( psz_node, "ABSTRACT", 8 ) ) { ReadElement( p_xml_reader, &psz_txt ); input_item_SetDescription( p_current_input, psz_txt ); } else /* Base Node handler */ if( !strncasecmp( psz_node, "BASE", 4 ) ) ReadElement( p_xml_reader, &psz_base ); else /* Entry Ref Handler */ if( !strncasecmp( psz_node, "ENTRYREF", 7 ) ) { const char *psz_tmp; do { psz_tmp = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while( psz_tmp && !strncasecmp( psz_tmp, "HREF", 4 ) ); /* Create new input item */ input_item_t *p_input; psz_txt = strdup( psz_node ); vlc_xml_decode( psz_txt ); p_input = input_item_New( psz_txt, psz_title_asx ); input_item_CopyOptions( p_current_input, p_input ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); } else /* Entry Handler */ if( !strncasecmp( psz_node, "ENTRY", 5 ) ) { ProcessEntry( &i_n_entry, p_xml_reader, p_subitems, p_current_input, psz_base); } /* FIXME Unsupported elements PARAM EVENT REPEAT ENDMARK STARTMARK */ } } while( i_type != XML_READER_ENDELEM || strncasecmp( psz_node, "ASX", 3 ) ); input_item_node_PostAndDelete( p_subitems ); p_subitems = NULL; error: free( psz_base ); free( psz_title_asx ); free( psz_entryref ); free( psz_txt ); if( p_xml_reader) xml_ReaderDelete( p_xml_reader ); if( p_subitems ) input_item_node_Delete( p_subitems ); vlc_gc_decref( p_current_input ); return 0; }
static void ProcessEntry( int *pi_n_entry, xml_reader_t *p_xml_reader, input_item_node_t *p_subitems, input_item_t *p_current_input, char *psz_prefix ) { const char *psz_node = NULL; const char *psz_txt = NULL; int i_type; char *psz_title = NULL; char *psz_artist = NULL; char *psz_copyright = NULL; char *psz_moreinfo = NULL; char *psz_description = NULL; char *psz_name = NULL; char *psz_mrl = NULL; char *psz_href = NULL; input_item_t *p_entry = NULL; int i_options; mtime_t i_start = 0; mtime_t i_duration = 0; char *ppsz_options[2]; do { i_type = xml_ReaderNextNode( p_xml_reader, &psz_node ); if( i_type == XML_READER_STARTELEM ) { /* Metadata Node */ if( !strncasecmp( psz_node, "TITLE", 5 ) ) ReadElement( p_xml_reader, &psz_title ); else if( !strncasecmp( psz_node, "AUTHOR", 6 ) ) ReadElement( p_xml_reader, &psz_artist ); else if( !strncasecmp( psz_node, "COPYRIGHT", 9 ) ) ReadElement( p_xml_reader, &psz_copyright ); else if( !strncasecmp( psz_node,"MOREINFO", 8 ) ) { do { psz_txt = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while(psz_txt && strncasecmp( psz_txt, "HREF", 4 ) ); if( !psz_txt ) ReadElement( p_xml_reader, &psz_moreinfo ); else psz_moreinfo = strdup( psz_node ); vlc_xml_decode( psz_moreinfo ); } else if( !strncasecmp( psz_node, "ABSTRACT", 8 ) ) ReadElement( p_xml_reader, &psz_description ); else if( !strncasecmp( psz_node, "DURATION", 8 ) ) i_duration = ParseTime( p_xml_reader ); else if( !strncasecmp( psz_node, "STARTTIME", 9 ) ) i_start = ParseTime( p_xml_reader ); else /* Reference Node */ /* All ref node will be converted into an entry */ if( !strncasecmp( psz_node, "REF", 3 ) ) { *pi_n_entry = *pi_n_entry + 1; if( !psz_title ) psz_title = input_item_GetTitle( p_current_input ); if( !psz_artist ) psz_artist = input_item_GetArtist( p_current_input ); if( !psz_copyright ) psz_copyright = input_item_GetCopyright( p_current_input ); if( !psz_description ) psz_description = input_item_GetDescription( p_current_input ); do { psz_txt = xml_ReaderNextAttr( p_xml_reader, &psz_node ); } while( strncasecmp( psz_txt, "HREF", 4) ); psz_href = strdup( psz_node ); if( asprintf( &psz_name, "%d. %s", *pi_n_entry, psz_title ) == -1) psz_name = strdup( psz_title ); vlc_xml_decode( psz_href ); psz_mrl = ProcessMRL( psz_href, psz_prefix ); /* Add Time information */ i_options = 0; if( i_start ) { if( asprintf( ppsz_options, ":start-time=%d" ,(int) i_start/1000000 ) != -1) i_options++; } if( i_duration) { if( asprintf( ppsz_options + i_options, ":stop-time=%d", (int) (i_start+i_duration)/1000000 ) != -1) i_options++; } /* Create the input item */ p_entry = input_item_NewExt( psz_mrl, psz_name, i_options, (const char* const*) ppsz_options, VLC_INPUT_OPTION_TRUSTED, i_duration ); input_item_CopyOptions( p_current_input, p_entry ); /* Add the metadata */ if( psz_name ) input_item_SetTitle( p_entry, psz_name ); if( psz_artist ) input_item_SetArtist( p_entry, psz_artist ); if( psz_copyright ) input_item_SetCopyright( p_entry, psz_copyright ); if( psz_moreinfo ) input_item_SetURL( p_entry, psz_moreinfo ); if( psz_description ) input_item_SetDescription( p_entry, psz_description ); if( i_duration > 0) input_item_SetDuration( p_entry, i_duration ); input_item_node_AppendItem( p_subitems, p_entry ); input_item_Release( p_entry ); while( i_options ) free( ppsz_options[--i_options] ); free( psz_name ); free( psz_mrl ); } } } while( i_type != XML_READER_ENDELEM || strncasecmp( psz_node, "ENTRY", 5 ) ); free( psz_href ); free( psz_title ); free( psz_artist ); free( psz_copyright ); free( psz_moreinfo ); free( psz_description ); }
/* radio stations: * <stationlist> * <tunein base="/sbin/tunein-station.pls"></tunein> * <station name="the name" * mt="mime type" * id="the id" * br="bit rate" * genre="A big genre string" * ct="current track name/author/..." * lc="listener count"></station> * </stationlist> * * TV stations: * <stationlist> * <tunein base="/sbin/tunein-station.pls"></tunein> * <station name="the name" * id="the id" * br="bit rate" * rt="rating" * load="server load ?" * ct="current track name/author/..." * genre="A big genre string" * lc="listener count"></station> * </stationlist> **/ static int DemuxStation( demux_t *p_demux, xml_reader_t *p_xml_reader, input_item_node_t *p_input_node, bool b_adult ) { char *psz_base = NULL; /* */ char *psz_name = NULL; /* genre name */ char *psz_mt = NULL; /* mime type */ char *psz_id = NULL; /* id */ char *psz_br = NULL; /* bit rate */ char *psz_genre = NULL; /* genre */ char *psz_ct = NULL; /* current track */ char *psz_lc = NULL; /* listener count */ /* If these are set then it's *not* a radio but a TV */ char *psz_rt = NULL; /* rating for shoutcast TV */ char *psz_load = NULL; /* load for shoutcast TV */ const char *node; /* tag name */ int i_type; while( (i_type = xml_ReaderNextNode( p_xml_reader, &node )) > 0 ) { switch( i_type ) { case XML_READER_STARTELEM: // Read the attributes if( !strcmp( node, "tunein" ) ) { const char *name, *value; while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) ) { if( !strcmp( name, "base" ) ) { free( psz_base ); psz_base = strdup( value ); } else msg_Warn( p_demux, "unexpected attribute %s in <%s>", name, node ); } } else if( !strcmp( node, "station" ) ) { const char *name, *value; while( (name = xml_ReaderNextAttr( p_xml_reader, &value )) ) { char **p = NULL; if( !strcmp( name, "name" ) ) p = &psz_name; else if ( !strcmp( name, "mt" ) ) p = &psz_mt; else if ( !strcmp( name, "id" ) ) p = &psz_id; else if ( !strcmp( name, "br" ) ) p = &psz_br; else if ( !strcmp( name, "genre" ) ) p = &psz_genre; else if ( !strcmp( name, "ct" ) ) p = &psz_ct; else if ( !strcmp( name, "lc" ) ) p = &psz_lc; else if ( !strcmp( name, "rt" ) ) p = &psz_rt; else if ( !strcmp( name, "load" ) ) p = &psz_load; if( p != NULL ) { free( *p ); *p = strdup( value ); } else msg_Warn( p_demux, "unexpected attribute %s in <%s>", name, node ); } } break; // End element case XML_READER_ENDELEM: if( !strcmp( node, "station" ) && ( psz_base || ( psz_rt && psz_load && ( b_adult || strcmp( psz_rt, "NC17" ) ) ) ) ) { char *psz_mrl = NULL; if( psz_rt || psz_load ) { /* tv */ if( asprintf( &psz_mrl, SHOUTCAST_TV_TUNEIN_URL "%s", psz_id ) == -1) psz_mrl = NULL; } else { /* radio */ if( asprintf( &psz_mrl, SHOUTCAST_TUNEIN_BASE_URL "%s?id=%s", psz_base, psz_id ) == -1 ) psz_mrl = NULL; } /* Create the item */ input_item_t *p_input = NULL; if( likely(psz_mrl != NULL) ) { vlc_xml_decode( psz_mrl ); p_input = input_item_New( psz_mrl, psz_name ); free( psz_mrl ); } if( likely(p_input != NULL) ) { input_item_CopyOptions( p_input_node->p_item, p_input ); #define SADD_INFO( type, field ) \ if( field ) \ input_item_AddInfo( p_input, _("Shoutcast"), \ vlc_gettext(type), "%s", field ) SADD_INFO( N_("Mime"), psz_mt ); SADD_INFO( N_("Bitrate"), psz_br ); SADD_INFO( N_("Listeners"), psz_lc ); SADD_INFO( N_("Load"), psz_load ); if( psz_genre ) input_item_SetGenre( p_input, psz_genre ); if( psz_ct ) input_item_SetNowPlaying( p_input, psz_ct ); if( psz_rt ) input_item_SetRating( p_input, psz_rt ); input_item_node_AppendItem( p_input_node, p_input ); vlc_gc_decref( p_input ); } FREENULL( psz_base ); FREENULL( psz_name ); FREENULL( psz_mt ); FREENULL( psz_id ); FREENULL( psz_br ); FREENULL( psz_genre ); FREENULL( psz_ct ); FREENULL( psz_lc ); FREENULL( psz_rt ); FREENULL( psz_load ); } break; } } /* FIXME: leaks on missing ENDELEMENT? */ return 0; }