static char* StreamExtractorCreateMRL( char const* base, char const* subentry ) { struct vlc_memstream buffer; char* escaped; if( mrl_EscapeFragmentIdentifier( &escaped, subentry ) ) return NULL; if( vlc_memstream_open( &buffer ) ) { free( escaped ); return NULL; } vlc_memstream_puts( &buffer, base ); if( !strstr( base, "#" ) ) vlc_memstream_putc( &buffer, '#' ); vlc_memstream_printf( &buffer, "!/%s", escaped ); free( escaped ); return vlc_memstream_close( &buffer ) ? NULL : buffer.ptr; }
static int Demux( demux_t* p_demux ) { demux_sys_t* p_sys = p_demux->p_sys; /* Last one must be an end time */ while( p_sys->times.i_current + 1 < p_sys->times.i_count && tt_time_Convert( &p_sys->times.p_array[p_sys->times.i_current] ) <= p_sys->i_next_demux_time ) { const int64_t i_playbacktime = tt_time_Convert( &p_sys->times.p_array[p_sys->times.i_current] ); const int64_t i_playbackendtime = tt_time_Convert( &p_sys->times.p_array[p_sys->times.i_current + 1] ) - 1; if ( !p_sys->b_slave && p_sys->b_first_time ) { es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + i_playbacktime ); p_sys->b_first_time = false; } struct vlc_memstream stream; if( vlc_memstream_open( &stream ) ) return VLC_DEMUXER_EGENERIC; tt_node_ToText( &stream, (tt_basenode_t *) p_sys->p_rootnode, &p_sys->times.p_array[p_sys->times.i_current] ); if( vlc_memstream_close( &stream ) == VLC_SUCCESS ) { block_t* p_block = block_heap_Alloc( stream.ptr, stream.length ); if( p_block ) { p_block->i_dts = p_block->i_pts = VLC_TS_0 + i_playbacktime; p_block->i_length = i_playbackendtime - i_playbacktime; es_out_Send( p_demux->out, p_sys->p_es, p_block ); } } p_sys->times.i_current++; } if ( !p_sys->b_slave ) { es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_next_demux_time ); p_sys->i_next_demux_time += CLOCK_FREQ / 8; } if( p_sys->times.i_current + 1 >= p_sys->times.i_count ) return VLC_DEMUXER_EOF; return VLC_DEMUXER_SUCCESS; }
int OpenDemux( vlc_object_t* p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; const uint8_t *p_peek; ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 ); if( unlikely( i_peek <= 32 ) ) return VLC_EGENERIC; const char *psz_xml = (const char *) p_peek; size_t i_xml = i_peek; /* Try to probe without xml module/loading the full document */ char *psz_alloc = NULL; switch( GetQWBE(p_peek) ) { /* See RFC 3023 Part 4 */ case UINT64_C(0xFFFE3C003F007800): /* UTF16 BOM<? */ case UINT64_C(0xFFFE3C003F007400): /* UTF16 BOM<t */ case UINT64_C(0xFEFF003C003F0078): /* UTF16 BOM<? */ case UINT64_C(0xFEFF003C003F0074): /* UTF16 BOM<t */ psz_alloc = FromCharset( "UTF-16", p_peek, i_peek ); break; case UINT64_C(0x3C003F0078006D00): /* UTF16-LE <?xm */ case UINT64_C(0x3C003F0074007400): /* UTF16-LE <tt */ psz_alloc = FromCharset( "UTF-16LE", p_peek, i_peek ); break; case UINT64_C(0x003C003F0078006D): /* UTF16-BE <?xm */ case UINT64_C(0x003C003F00740074): /* UTF16-BE <tt */ psz_alloc = FromCharset( "UTF-16BE", p_peek, i_peek ); break; case UINT64_C(0xEFBBBF3C3F786D6C): /* UTF8 BOM<?xml */ case UINT64_C(0x3C3F786D6C207665): /* UTF8 <?xml ve */ case UINT64_C(0xEFBBBF3C74742078): /* UTF8 BOM<tt x*/ break; default: if(GetDWBE(p_peek) != UINT32_C(0x3C747420)) /* tt node without xml document marker */ return VLC_EGENERIC; } if( psz_alloc ) { psz_xml = psz_alloc; i_xml = strlen( psz_alloc ); } /* Simplified probing. Valid TTML must have a namespace declaration */ const char *psz_tt = strnstr( psz_xml, "tt ", i_xml ); if( !psz_tt || psz_tt == psz_xml || (psz_tt[-1] != ':' && psz_tt[-1] != '<') ) { free( psz_alloc ); return VLC_EGENERIC; } else { const char * const rgsz[] = { "=\"http://www.w3.org/ns/ttml\"", "=\"http://www.w3.org/2004/11/ttaf1\"", "=\"http://www.w3.org/2006/04/ttaf1\"", "=\"http://www.w3.org/2006/10/ttaf1\"", }; const char *psz_ns = NULL; for( size_t i=0; i<ARRAY_SIZE(rgsz) && !psz_ns; i++ ) { psz_ns = strnstr( psz_xml, rgsz[i], i_xml - (psz_tt - psz_xml) ); } free( psz_alloc ); if( !psz_ns ) return VLC_EGENERIC; } p_demux->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) ); if( unlikely( p_sys == NULL ) ) return VLC_ENOMEM; p_sys->b_first_time = true; p_sys->temporal_extent.i_type = TT_TIMINGS_PARALLEL; tt_time_Init( &p_sys->temporal_extent.begin ); tt_time_Init( &p_sys->temporal_extent.end ); tt_time_Init( &p_sys->temporal_extent.dur ); p_sys->temporal_extent.begin.base = 0; p_sys->p_xml = xml_Create( p_demux ); if( !p_sys->p_xml ) goto error; p_sys->p_reader = xml_ReaderCreate( p_sys->p_xml, p_demux->s ); if( !p_sys->p_reader ) goto error; #ifndef TTML_DEMUX_DEBUG p_sys->p_reader->obj.flags |= OBJECT_FLAGS_QUIET; #endif if( ReadTTML( p_demux ) != VLC_SUCCESS ) goto error; tt_timings_Resolve( (tt_basenode_t *) p_sys->p_rootnode, &p_sys->temporal_extent, &p_sys->times.p_array, &p_sys->times.i_count ); #ifdef TTML_DEMUX_DEBUG { struct vlc_memstream stream; if( vlc_memstream_open( &stream ) ) goto error; tt_time_t t; tt_time_Init( &t ); tt_node_ToText( &stream, (tt_basenode_t*)p_sys->p_rootnode, &t /* invalid */ ); vlc_memstream_putc( &stream, '\0' ); if( vlc_memstream_close( &stream ) == VLC_SUCCESS ) { msg_Dbg( p_demux, "%s", stream.ptr ); free( stream.ptr ); } } #endif p_demux->pf_demux = Demux; p_demux->pf_control = Control; es_format_t fmt; es_format_Init( &fmt, SPU_ES, VLC_CODEC_TTML ); p_sys->p_es = es_out_Add( p_demux->out, &fmt ); if( !p_sys->p_es ) goto error; es_format_Clean( &fmt ); return VLC_SUCCESS; error: CloseDemux( p_demux ); return VLC_EGENERIC; }
/***************************************************************************** * 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; }
/***************************************************************************** * Run : call Handshake() then submit songs *****************************************************************************/ static void *Run(void *data) { intf_thread_t *p_intf = data; uint8_t p_buffer[1024]; int canc = vlc_savecancel(); bool b_handshaked = false; bool b_nowp_submission_ongoing = false; /* data about audioscrobbler session */ vlc_tick_t next_exchange = VLC_TICK_INVALID; /**< when can we send data */ unsigned int i_interval = 0; /**< waiting interval (secs)*/ intf_sys_t *p_sys = p_intf->p_sys; /* main loop */ for (;;) { vlc_restorecancel(canc); if (next_exchange != VLC_TICK_INVALID) vlc_tick_wait(next_exchange); vlc_mutex_lock(&p_sys->lock); mutex_cleanup_push(&p_sys->lock); while (p_sys->i_songs == 0 && p_sys->b_submit_nowp == false) vlc_cond_wait(&p_sys->wait, &p_sys->lock); vlc_cleanup_pop(); vlc_mutex_unlock(&p_sys->lock); canc = vlc_savecancel(); /* handshake if needed */ if (!b_handshaked) { msg_Dbg(p_intf, "Handshaking with last.fm ..."); switch(Handshake(p_intf)) { case VLC_ENOMEM: goto out; case VLC_ENOVAR: /* username not set */ vlc_dialog_display_error(p_intf, _("Last.fm username not set"), "%s", _("Please set a username or disable the " "audioscrobbler plugin, and restart VLC.\n" "Visit http://www.last.fm/join/ to get an account.")); goto out; case VLC_SUCCESS: msg_Dbg(p_intf, "Handshake successful :)"); b_handshaked = true; i_interval = 0; next_exchange = VLC_TICK_INVALID; break; case VLC_AUDIOSCROBBLER_EFATAL: msg_Warn(p_intf, "Exiting..."); goto out; case VLC_EGENERIC: default: /* protocol error : we'll try later */ HandleInterval(&next_exchange, &i_interval); break; } /* if handshake failed let's restart the loop */ if (!b_handshaked) continue; } msg_Dbg(p_intf, "Going to submit some data..."); vlc_url_t *url; struct vlc_memstream req, payload; vlc_memstream_open(&payload); vlc_memstream_printf(&payload, "s=%s", p_sys->psz_auth_token); /* forge the HTTP POST request */ vlc_mutex_lock(&p_sys->lock); if (p_sys->b_submit_nowp) { audioscrobbler_song_t *p_song = &p_sys->p_current_song; b_nowp_submission_ongoing = true; url = &p_sys->p_nowp_url; vlc_memstream_printf(&payload, "&a=%s", p_song->psz_a); vlc_memstream_printf(&payload, "&t=%s", p_song->psz_t); vlc_memstream_puts(&payload, "&b="); if (p_song->psz_b != NULL) vlc_memstream_puts(&payload, p_song->psz_b); vlc_memstream_printf(&payload, "&l=%d", p_song->i_l); vlc_memstream_puts(&payload, "&n="); if (p_song->psz_n != NULL) vlc_memstream_puts(&payload, p_song->psz_n); vlc_memstream_puts(&payload, "&m="); if (p_song->psz_m != NULL) vlc_memstream_puts(&payload, p_song->psz_m); } else { url = &p_sys->p_submit_url; for (int i_song = 0 ; i_song < p_sys->i_songs ; i_song++) { audioscrobbler_song_t *p_song = &p_sys->p_queue[i_song]; vlc_memstream_printf(&payload, "&a%%5B%d%%5D=%s", i_song, p_song->psz_a); vlc_memstream_printf(&payload, "&t%%5B%d%%5D=%s", i_song, p_song->psz_t); vlc_memstream_printf(&payload, "&i%%5B%d%%5D=%"PRIu64, i_song, (uint64_t)p_song->date); vlc_memstream_printf(&payload, "&o%%5B%d%%5D=P", i_song); vlc_memstream_printf(&payload, "&r%%5B%d%%5D=", i_song); vlc_memstream_printf(&payload, "&l%%5B%d%%5D=%d", i_song, p_song->i_l); vlc_memstream_printf(&payload, "&b=%%5B%d%%5D=", i_song); if (p_song->psz_b != NULL) vlc_memstream_puts(&payload, p_song->psz_b); vlc_memstream_printf(&payload, "&n=%%5B%d%%5D=", i_song); if (p_song->psz_n != NULL) vlc_memstream_puts(&payload, p_song->psz_n); vlc_memstream_printf(&payload, "&m=%%5B%d%%5D=", i_song); if (p_song->psz_m != NULL) vlc_memstream_puts(&payload, p_song->psz_m); } } vlc_mutex_unlock(&p_sys->lock); if (vlc_memstream_close(&payload)) goto out; vlc_memstream_open(&req); vlc_memstream_printf(&req, "POST %s HTTP/1.1\r\n", url->psz_path); vlc_memstream_printf(&req, "Host: %s\r\n", url->psz_host); vlc_memstream_puts(&req, "User-Agent:" " "PACKAGE_NAME"/"PACKAGE_VERSION"\r\n"); vlc_memstream_puts(&req, "Connection: close\r\n"); vlc_memstream_puts(&req, "Accept-Encoding: identity\r\n"); vlc_memstream_puts(&req, "Content-Type:" " application/x-www-form-urlencoded\r\n"); vlc_memstream_printf(&req, "Content-Length: %zu\r\n", payload.length); vlc_memstream_puts(&req, "\r\n"); /* Could avoid copying payload with iovec... but efforts */ vlc_memstream_write(&req, payload.ptr, payload.length); vlc_memstream_puts(&req, "\r\n\r\n"); free(payload.ptr); if (vlc_memstream_close(&req)) /* Out of memory */ goto out; vlc_tls_t *sock = vlc_tls_SocketOpenTCP(VLC_OBJECT(p_intf), url->psz_host, url->i_port); if (sock == NULL) { /* If connection fails, we assume we must handshake again */ HandleInterval(&next_exchange, &i_interval); b_handshaked = false; free(req.ptr); continue; } /* we transmit the data */ int i_net_ret = vlc_tls_Write(sock, req.ptr, req.length); free(req.ptr); if (i_net_ret == -1) { /* If connection fails, we assume we must handshake again */ HandleInterval(&next_exchange, &i_interval); b_handshaked = false; vlc_tls_Close(sock); continue; } /* FIXME: this might wait forever */ /* FIXME: With TCP, you should never assume that a single read will * return the entire response... */ i_net_ret = vlc_tls_Read(sock, p_buffer, sizeof(p_buffer) - 1, false); vlc_tls_Close(sock); if (i_net_ret <= 0) { /* if we get no answer, something went wrong : try again */ continue; } p_buffer[i_net_ret] = '\0'; char *failed = strstr((char *) p_buffer, "FAILED"); if (failed) { msg_Warn(p_intf, "%s", failed); HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "BADSESSION")) { msg_Err(p_intf, "Authentication failed (BADSESSION), are you connected to last.fm with another program ?"); b_handshaked = false; HandleInterval(&next_exchange, &i_interval); continue; } if (strstr((char *) p_buffer, "OK")) { if (b_nowp_submission_ongoing) { b_nowp_submission_ongoing = false; p_sys->b_submit_nowp = false; } else { for (int i = 0; i < p_sys->i_songs; i++) DeleteSong(&p_sys->p_queue[i]); p_sys->i_songs = 0; } i_interval = 0; next_exchange = VLC_TICK_INVALID; msg_Dbg(p_intf, "Submission successful!"); } else { msg_Err(p_intf, "Authentication failed, handshaking again (%s)", p_buffer); b_handshaked = false; HandleInterval(&next_exchange, &i_interval); } } out: vlc_restorecancel(canc); return NULL; }
/* takes all values in the values of vlc_keystore_entry * * and formats them in a url key */ static char* values2key( const char* const* ppsz_values, bool b_search ) { char* psz_b64_realm = NULL; char* psz_b64_auth = NULL; bool b_state = false; if ( ( !ppsz_values[KEY_PROTOCOL] || !ppsz_values[KEY_SERVER] ) && !b_search ) return NULL; struct vlc_memstream ms; if ( vlc_memstream_open( &ms ) ) return NULL; /* Protocol section */ if ( ppsz_values[KEY_PROTOCOL] ) vlc_memstream_printf( &ms, "%s://", ppsz_values[KEY_PROTOCOL] ); else if ( b_search ) vlc_memstream_printf( &ms, "*://" ); /* User section */ if ( ppsz_values[KEY_USER] ) vlc_memstream_printf( &ms, "%s@", ppsz_values[KEY_USER] ); else if ( b_search ) vlc_memstream_printf( &ms, "*" ); /* Server section */ if ( ppsz_values[KEY_SERVER] ) vlc_memstream_printf( &ms, "%s", ppsz_values[KEY_SERVER] ); else if ( b_search ) vlc_memstream_printf( &ms, "*" ); /* Port section */ if ( ppsz_values[KEY_PORT] ) vlc_memstream_printf( &ms, ":%s", ppsz_values[KEY_PORT] ); else if ( b_search ) vlc_memstream_printf( &ms, "*" ); /* Path section */ if( ppsz_values[KEY_PATH] ) { if( ppsz_values[KEY_PATH][0] != '/' ) vlc_memstream_putc( &ms, '/' ); vlc_memstream_puts( &ms, ppsz_values[KEY_PATH] ); } else if ( b_search ) vlc_memstream_printf( &ms, "*" ); /* Realm and authtype section */ if ( ppsz_values[KEY_REALM] || ppsz_values[KEY_AUTHTYPE] || b_search ) { vlc_memstream_printf( &ms, "?" ); /* Realm section */ if ( ppsz_values[KEY_REALM] || b_search ) { if ( ppsz_values[KEY_REALM] ) { psz_b64_realm = vlc_b64_encode_binary( ( uint8_t* )ppsz_values[KEY_REALM], strlen(ppsz_values[KEY_REALM] ) ); if ( !psz_b64_realm ) goto end; vlc_memstream_printf( &ms, "realm=%s", psz_b64_realm ); } else vlc_memstream_printf( &ms, "*" ); if ( ppsz_values[KEY_AUTHTYPE] ) vlc_memstream_printf( &ms, "&" ); } /* Authtype section */ if ( ppsz_values[KEY_AUTHTYPE] || b_search ) { if ( ppsz_values[KEY_AUTHTYPE] ) { psz_b64_auth = vlc_b64_encode_binary( ( uint8_t* )ppsz_values[KEY_AUTHTYPE], strlen(ppsz_values[KEY_AUTHTYPE] ) ); if ( !psz_b64_auth ) goto end; vlc_memstream_printf( &ms, "authtype=%s", psz_b64_auth ); } else vlc_memstream_printf( &ms, "*" ); } } b_state = true; end: free( psz_b64_realm ); free( psz_b64_auth ); if ( vlc_memstream_flush( &ms ) != 0 ) b_state = false; char *psz_key = vlc_memstream_close( &ms ) == 0 ? ms.ptr : NULL; if ( !b_state ) { free( psz_key ); psz_key = NULL; } return psz_key; }