int DoAcoustIdWebRequest( vlc_object_t *p_obj, acoustid_fingerprint_t *p_data ) { if ( !p_data->psz_fingerprint ) return VLC_SUCCESS; char *psz_url; if( unlikely(asprintf( &psz_url, "https://fingerprint.videolan.org/" "acoustid.php?meta=recordings+tracks+usermeta+" "releases&duration=%d&fingerprint=%s", p_data->i_duration, p_data->psz_fingerprint ) < 1 ) ) return VLC_EGENERIC; msg_Dbg( p_obj, "Querying AcoustID from %s", psz_url ); int i_saved_flags = p_obj->obj.flags; p_obj->obj.flags |= OBJECT_FLAGS_NOINTERACT; stream_t *p_stream = vlc_stream_NewURL( p_obj, psz_url ); free( psz_url ); p_obj->obj.flags = i_saved_flags; if ( p_stream == NULL ) return VLC_EGENERIC; stream_t *p_chain = vlc_stream_FilterNew( p_stream, "inflate" ); if( p_chain ) p_stream = p_chain; /* read answer */ char *p_buffer = NULL; int i_ret = 0; for( ;; ) { int i_read = 65536; if( i_ret >= INT_MAX - i_read ) break; p_buffer = realloc_or_free( p_buffer, 1 + i_ret + i_read ); if( unlikely(p_buffer == NULL) ) { vlc_stream_Delete( p_stream ); return VLC_ENOMEM; } i_read = vlc_stream_Read( p_stream, &p_buffer[i_ret], i_read ); if( i_read <= 0 ) break; i_ret += i_read; } vlc_stream_Delete( p_stream ); p_buffer[i_ret] = 0; if ( ParseJson( p_obj, p_buffer, & p_data->results ) ) msg_Dbg( p_obj, "results count == %d", p_data->results.count ); else msg_Dbg( p_obj, "No results" ); free( p_buffer ); return VLC_SUCCESS; }
static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url, video_format_t *p_fmt_in, video_format_t *p_fmt_out ) { block_t *p_block; picture_t *p_pic; stream_t *p_stream = NULL; uint64_t i_size; p_stream = vlc_stream_NewMRL( p_image->p_parent, psz_url ); if( !p_stream ) { msg_Dbg( p_image->p_parent, "could not open %s for reading", psz_url ); return NULL; } if( vlc_stream_GetSize( p_stream, &i_size ) || i_size > SSIZE_MAX ) { msg_Dbg( p_image->p_parent, "could not read %s", psz_url ); goto error; } p_block = vlc_stream_Block( p_stream, i_size ); if( p_block == NULL ) goto error; if( !p_fmt_in->i_chroma ) { char *psz_mime = stream_ContentType( p_stream ); if( psz_mime != NULL ) { p_fmt_in->i_chroma = image_Mime2Fourcc( psz_mime ); free( psz_mime ); } } vlc_stream_Delete( p_stream ); if( !p_fmt_in->i_chroma ) { /* Try to guess format from file name */ p_fmt_in->i_chroma = image_Ext2Fourcc( psz_url ); } p_pic = ImageRead( p_image, p_block, p_fmt_in, p_fmt_out ); return p_pic; error: vlc_stream_Delete( p_stream ); return NULL; }
/***************************************************************************** * Import_podcast: main import function *****************************************************************************/ int Import_podcast( vlc_object_t *p_this ) { stream_t *p_demux = (stream_t *)p_this; CHECK_FILE(p_demux); if( stream_IsMimeType( p_demux->s, "text/xml" ) || stream_IsMimeType( p_demux->s, "application/xml" ) ) { /* XML: check if the root node is "rss". Use a specific peeked * probestream in order to not modify the source state while probing. * */ const uint8_t *p_peek; ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 ); if( unlikely( i_peek <= 0 ) ) return VLC_EGENERIC; stream_t *p_probestream = vlc_stream_MemoryNew( p_demux, (uint8_t *)p_peek, i_peek, true ); if( unlikely( !p_probestream ) ) return VLC_EGENERIC; xml_reader_t *p_xml_reader = xml_ReaderCreate( p_demux, p_probestream ); if( !p_xml_reader ) { vlc_stream_Delete( p_probestream ); return VLC_EGENERIC; } const char *node; int ret; if( ( ret = xml_ReaderNextNode( p_xml_reader, &node ) ) != XML_READER_STARTELEM || strcmp( node, "rss" ) ) { vlc_stream_Delete( p_probestream ); xml_ReaderDelete( p_xml_reader ); return VLC_EGENERIC; } xml_ReaderDelete( p_xml_reader ); vlc_stream_Delete( p_probestream ); /* SUCCESS: this text/xml is a rss file */ } else if( !stream_IsMimeType( p_demux->s, "application/rss+xml" ) ) return VLC_EGENERIC; p_demux->pf_readdir = ReadDir; p_demux->pf_control = access_vaDirectoryControlHelper; msg_Dbg( p_demux, "using podcast reader" ); return VLC_SUCCESS; }
static int Seek(access_t *access, uint64_t position) { access_sys_t *sys = access->p_sys; const rar_file_t *file = sys->file; if (position > file->real_size) position = file->real_size; sys->position = position; /* Search the chunk */ const rar_file_chunk_t *old_chunk = sys->chunk; for (int i = 0; i < file->chunk_count; i++) { sys->chunk = file->chunk[i]; if (position < sys->chunk->cummulated_size + sys->chunk->size) break; } const uint64_t offset = sys->chunk->offset + (position - sys->chunk->cummulated_size); if (strcmp(old_chunk->mrl, sys->chunk->mrl)) { if (sys->s) vlc_stream_Delete(sys->s); sys->s = vlc_stream_NewMRL(access, sys->chunk->mrl); } return sys->s ? vlc_stream_Seek(sys->s, offset) : VLC_EGENERIC; }
vlc_demux_chained_t *vlc_demux_chained_New(vlc_object_t *parent, const char *name, es_out_t *out) { vlc_demux_chained_t *dc = malloc(sizeof (*dc) + strlen(name) + 1); if (unlikely(dc == NULL)) return NULL; dc->writer = vlc_stream_fifo_New(parent, &dc->reader); if (dc->writer == NULL) { free(dc); return NULL; } dc->stats.position = 0.; dc->stats.length = 0; dc->stats.time = 0; dc->out = out; strcpy(dc->name, name); vlc_mutex_init(&dc->lock); if (vlc_clone(&dc->thread, vlc_demux_chained_Thread, dc, VLC_THREAD_PRIORITY_INPUT)) { vlc_stream_Delete(dc->reader); vlc_stream_fifo_Close(dc->writer); vlc_mutex_destroy(&dc->lock); free(dc); dc = NULL; } return dc; }
static int Find( addons_finder_t *p_finder ) { bool b_done = false; while ( !b_done ) { char *psz_uri = NULL; if ( ! asprintf( &psz_uri, ADDONS_REPO_SCHEMEHOST"/xml" ) ) return VLC_ENOMEM; b_done = true; stream_t *p_stream = vlc_stream_NewURL_ND( p_finder, psz_uri ); free( psz_uri ); if ( !p_stream ) return VLC_EGENERIC; if ( ! ParseCategoriesInfo( p_finder, p_stream ) ) { /* no more entries have been read: was last page or error */ b_done = true; } vlc_stream_Delete( p_stream ); } return VLC_SUCCESS; }
static access_t *GetAccess(access_t *access) { access_sys_t *sys = access->p_sys; access_t *a = sys->access; if (a != NULL) { if (!vlc_stream_Eof(a)) return a; vlc_stream_Delete(a); sys->access = NULL; } if (sys->next == NULL) return NULL; a = vlc_access_NewMRL(VLC_OBJECT(access), sys->next->mrl); if (a == NULL) return NULL; sys->access = a; sys->next = sys->next->next; return a; }
static void StreamDelete( stream_t *s ) { module_unneed( s, s->p_module ); if( s->p_source ) vlc_stream_Delete( s->p_source ); }
static void StreamDelete(stream_t *s) { struct vlc_stream_filter_private *priv = vlc_stream_Private(s); module_unneed(s, priv->module); vlc_stream_Delete(s->s); free(s->psz_filepath); }
void RarAccessClose(vlc_object_t *object) { access_t *access = (access_t*)object; access_sys_t *sys = access->p_sys; if (sys->s) vlc_stream_Delete(sys->s); RarFileDelete(sys->file); free(sys); }
static int Find( addons_finder_t *p_finder ) { stream_t *p_stream = vlc_stream_NewURL_ND( p_finder, ADDONS_REPO_SCHEMEHOST "/xml" ); if ( !p_stream ) return VLC_EGENERIC; int i_res = ParseCategoriesInfo( p_finder, p_stream ); vlc_stream_Delete( p_stream ); return i_res > 0 ? VLC_SUCCESS : VLC_EGENERIC; }
static int SwitchCallback(struct archive *p_archive, void *p_object, void *p_object2) { VLC_UNUSED(p_archive); callback_data_t *p_data = (callback_data_t *) p_object; callback_data_t *p_nextdata = (callback_data_t *) p_object2; access_sys_t *p_sys = p_data->p_access->p_sys; msg_Dbg(p_data->p_access, "opening next volume %s", p_nextdata->psz_uri); vlc_stream_Delete(p_sys->p_stream); p_sys->p_stream = vlc_stream_NewURL(p_nextdata->p_access, p_nextdata->psz_uri); return p_sys->p_stream ? ARCHIVE_OK : ARCHIVE_FATAL; }
/** Replacement for luaL_dofile, using VLC's input capabilities */ int vlclua_dofile( vlc_object_t *p_this, lua_State *L, const char *curi ) { char *uri = ToLocaleDup( curi ); if( !strstr( uri, "://" ) ) { int ret = luaL_dofile( L, uri ); free( uri ); return ret; } if( !strncasecmp( uri, "file://", 7 ) ) { int ret = luaL_dofile( L, uri + 7 ); free( uri ); return ret; } stream_t *s = vlc_stream_NewURL( p_this, uri ); if( !s ) { free( uri ); return 1; } int64_t i_size = stream_Size( s ); char *p_buffer = ( i_size > 0 ) ? malloc( i_size ) : NULL; if( !p_buffer ) { // FIXME: read the whole stream until we reach the end (if no size) vlc_stream_Delete( s ); free( uri ); return 1; } int64_t i_read = vlc_stream_Read( s, p_buffer, (int) i_size ); int i_ret = ( i_read == i_size ) ? 0 : 1; if( !i_ret ) i_ret = luaL_loadbuffer( L, p_buffer, (size_t) i_size, uri ); if( !i_ret ) i_ret = lua_pcall( L, 0, LUA_MULTRET, 0 ); vlc_stream_Delete( s ); free( p_buffer ); free( uri ); return i_ret; }
static int CloseCallback(struct archive *p_archive, void *p_object) { VLC_UNUSED(p_archive); callback_data_t *p_data = (callback_data_t *) p_object; access_sys_t *p_sys = p_data->p_access->p_sys; if (p_sys->p_stream) { vlc_stream_Delete(p_sys->p_stream); p_sys->p_stream = NULL; } return ARCHIVE_OK; }
/** * Release the private data associated with a stream-extractor * \param priv pointer to the private section */ static void se_Release( struct stream_extractor_private* priv ) { if( priv->pf_clean ) priv->pf_clean( priv ); if( priv->module ) { module_unneed( priv->object, priv->module ); if( priv->source ) vlc_stream_Delete( priv->source ); } vlc_object_release( priv->object ); }
static void *vlc_demux_chained_Thread(void *data) { vlc_demux_chained_t *dc = data; demux_t *demux = demux_New(VLC_OBJECT(dc->reader), dc->name, dc->reader, dc->out); if (demux == NULL) { vlc_stream_Delete(dc->reader); return NULL; } /* Stream FIFO cannot apply DVB filters. * Get all programs and let the E/S output sort them out. */ demux_Control(demux, DEMUX_SET_GROUP_ALL); /* Main loop */ vlc_tick_t next_update = 0; do if (demux_TestAndClearFlags(demux, UINT_MAX) || vlc_tick_now() >= next_update) { double newpos; vlc_tick_t newlen; vlc_tick_t newtime; if (demux_Control(demux, DEMUX_GET_POSITION, &newpos)) newpos = 0.; if (demux_Control(demux, DEMUX_GET_LENGTH, &newlen)) newlen = 0; if (demux_Control(demux, DEMUX_GET_TIME, &newtime)) newtime = 0; vlc_mutex_lock(&dc->lock); dc->stats.position = newpos; dc->stats.length = newlen; dc->stats.time = newtime; vlc_mutex_unlock(&dc->lock); next_update = vlc_tick_now() + VLC_TICK_FROM_MS(250); } while (demux_Demux(demux) > 0); demux_Delete(demux); return NULL; }
static int libarchive_exit_cb( libarchive_t* p_arc, void* p_obj ) { VLC_UNUSED( p_arc ); libarchive_callback_t* p_cb = (libarchive_callback_t*)p_obj; if( p_cb->p_sys->source == p_cb->p_source ) { /* DO NOT CLOSE OUR MOTHER STREAM */ if( !p_cb->p_sys->b_dead && vlc_stream_Seek( p_cb->p_source, 0 ) ) return ARCHIVE_FATAL; } else if( p_cb->p_source ) { vlc_stream_Delete( p_cb->p_source ); p_cb->p_source = NULL; } return ARCHIVE_OK; }
static int FindVolumes(access_t *p_access, struct archive *p_archive, const char *psz_uri, char *** const pppsz_files, unsigned int * const pi_files) { VLC_UNUSED(p_archive); *pppsz_files = NULL; *pi_files = 0; static const struct { char const * const psz_match; char const * const psz_format; uint16_t i_min; uint16_t i_max; } patterns[] = { { ".part1.rar", "%.*s.part%.1d.rar", 2, 9 }, { ".part01.rar", "%.*s.part%.2d.rar", 2, 99 }, { ".part001.rar", "%.*s.part%.3d.rar", 2, 999 }, { ".001", "%.*s.%.3d", 2, 999 }, { ".000", "%.*s.%.3d", 1, 999 }, }; const int i_uri_size = strlen(psz_uri); const size_t i_patterns = ARRAY_SIZE(patterns); for (size_t i = 0; i < i_patterns; i++) { const int i_match_size = strlen(patterns[i].psz_match); if (i_uri_size < i_match_size) continue; if (!strcmp(&psz_uri[i_uri_size - i_match_size], patterns[i].psz_match)) { char **ppsz_files = xmalloc(sizeof(char *) * patterns[i].i_max); for (unsigned j = patterns[i].i_min; j < patterns[i].i_max; j++) { char *psz_newuri; if (asprintf(&psz_newuri, patterns[i].psz_format, i_uri_size - i_match_size, psz_uri, j) == -1) break; /* Probe URI */ int i_savedflags = p_access->obj.flags; p_access->obj.flags |= OBJECT_FLAGS_NOINTERACT; stream_t *p_stream = vlc_stream_NewURL(p_access, psz_newuri); p_access->obj.flags = i_savedflags; if (p_stream) { ppsz_files[*pi_files] = psz_newuri; (*pi_files)++; vlc_stream_Delete(p_stream); } else { free(psz_newuri); break; } } if (*pi_files == 0) FREENULL(ppsz_files); *pppsz_files = ppsz_files; return VLC_SUCCESS; } } return VLC_SUCCESS; }
static int vlclua_stream_delete( lua_State *L ) { stream_t **pp_stream = (stream_t **)luaL_checkudata( L, 1, "stream" ); vlc_stream_Delete( *pp_stream ); return 0; }
/***************************************************************************** * Open: initializes matroska demux structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; matroska_stream_c *p_stream; matroska_segment_c *p_segment; const uint8_t *p_peek; std::string s_path, s_filename; vlc_stream_io_callback *p_io_callback; EbmlStream *p_io_stream; bool b_need_preload = false; /* peek the begining */ if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC; /* is a valid file */ if( p_peek[0] != 0x1a || p_peek[1] != 0x45 || p_peek[2] != 0xdf || p_peek[3] != 0xa3 ) return VLC_EGENERIC; /* Set the demux function */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = new demux_sys_t( *p_demux ); p_io_callback = new vlc_stream_io_callback( p_demux->s, false ); p_io_stream = new (std::nothrow) EbmlStream( *p_io_callback ); if( p_io_stream == NULL ) { msg_Err( p_demux, "failed to create EbmlStream" ); delete p_io_callback; delete p_sys; return VLC_EGENERIC; } p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_io_stream, true ); if( p_stream == NULL ) { msg_Err( p_demux, "cannot find KaxSegment or missing mandatory KaxInfo" ); goto error; } p_sys->streams.push_back( p_stream ); p_stream->p_io_callback = p_io_callback; p_stream->p_estream = p_io_stream; for (size_t i=0; i<p_stream->segments.size(); i++) { p_stream->segments[i]->Preload(); b_need_preload |= p_stream->segments[i]->b_ref_external_segments; if ( p_stream->segments[i]->translations.size() && p_stream->segments[i]->translations[0]->codec_id == MATROSKA_CHAPTER_CODEC_DVD && p_stream->segments[i]->families.size() ) b_need_preload = true; } p_segment = p_stream->segments[0]; if( p_segment->cluster == NULL && p_segment->stored_editions.size() == 0 ) { msg_Err( p_demux, "cannot find any cluster or chapter, damaged file ?" ); goto error; } if (b_need_preload && var_InheritBool( p_demux, "mkv-preload-local-dir" )) { msg_Dbg( p_demux, "Preloading local dir" ); /* get the files from the same dir from the same family (based on p_demux->psz_path) */ if ( p_demux->psz_file && !strcmp( p_demux->psz_access, "file" ) ) { // assume it's a regular file // get the directory path s_path = p_demux->psz_file; if (s_path.at(s_path.length() - 1) == DIR_SEP_CHAR) { s_path = s_path.substr(0,s_path.length()-1); } else { if (s_path.find_last_of(DIR_SEP_CHAR) > 0) { s_path = s_path.substr(0,s_path.find_last_of(DIR_SEP_CHAR)); } } DIR *p_src_dir = vlc_opendir(s_path.c_str()); if (p_src_dir != NULL) { const char *psz_file; while ((psz_file = vlc_readdir(p_src_dir)) != NULL) { if (strlen(psz_file) > 4) { s_filename = s_path + DIR_SEP_CHAR + psz_file; #if defined(_WIN32) || defined(__OS2__) if (!strcasecmp(s_filename.c_str(), p_demux->psz_file)) #else if (!s_filename.compare(p_demux->psz_file)) #endif { continue; // don't reuse the original opened file } if (!s_filename.compare(s_filename.length() - 3, 3, "mkv") || !s_filename.compare(s_filename.length() - 3, 3, "mka")) { // test whether this file belongs to our family const uint8_t *p_peek; bool file_ok = false; char *psz_url = vlc_path2uri( s_filename.c_str(), "file" ); stream_t *p_file_stream = vlc_stream_NewURL( p_demux, psz_url ); /* peek the begining */ if( p_file_stream && vlc_stream_Peek( p_file_stream, &p_peek, 4 ) >= 4 && p_peek[0] == 0x1a && p_peek[1] == 0x45 && p_peek[2] == 0xdf && p_peek[3] == 0xa3 ) file_ok = true; if ( file_ok ) { vlc_stream_io_callback *p_file_io = new vlc_stream_io_callback( p_file_stream, true ); EbmlStream *p_estream = new EbmlStream(*p_file_io); p_stream = p_sys->AnalyseAllSegmentsFound( p_demux, p_estream ); if ( p_stream == NULL ) { msg_Dbg( p_demux, "the file '%s' will not be used", s_filename.c_str() ); delete p_estream; delete p_file_io; } else { p_stream->p_io_callback = p_file_io; p_stream->p_estream = p_estream; p_sys->streams.push_back( p_stream ); } } else { if( p_file_stream ) { vlc_stream_Delete( p_file_stream ); } msg_Dbg( p_demux, "the file '%s' cannot be opened", s_filename.c_str() ); } free( psz_url ); } } } closedir( p_src_dir ); } } p_sys->PreloadFamily( *p_segment ); } else if (b_need_preload) msg_Warn( p_demux, "This file references other files, you may want to enable the preload of local directory"); if ( !p_sys->PreloadLinked() || !p_sys->PreparePlayback( *p_sys->p_current_vsegment, 0 ) ) { msg_Err( p_demux, "cannot use the segment" ); goto error; } p_sys->FreeUnused(); p_sys->InitUi(); return VLC_SUCCESS; error: delete p_sys; return VLC_EGENERIC; }
static int Retrieve( addons_finder_t *p_finder, addon_entry_t *p_entry ) { vlc_mutex_lock( &p_entry->lock ); if ( !p_entry->psz_archive_uri ) { vlc_mutex_unlock( &p_entry->lock ); return VLC_EGENERIC; } char *psz_archive_uri = strdup( p_entry->psz_archive_uri ); vlc_mutex_unlock( &p_entry->lock ); if ( !psz_archive_uri ) return VLC_ENOMEM; /* get archive and parse manifest */ stream_t *p_stream; if ( psz_archive_uri[0] == '/' ) { /* Relative path */ char *psz_uri; if ( ! asprintf( &psz_uri, ADDONS_REPO_SCHEMEHOST"%s", psz_archive_uri ) ) { free( psz_archive_uri ); return VLC_ENOMEM; } p_stream = vlc_stream_NewURL_ND( p_finder, psz_uri ); free( psz_uri ); } else { p_stream = vlc_stream_NewURL_ND( p_finder, psz_archive_uri ); } msg_Dbg( p_finder, "downloading archive %s", psz_archive_uri ); free ( psz_archive_uri ); if ( !p_stream ) return VLC_EGENERIC; /* In case of pf_ reuse */ if ( p_finder->p_sys->psz_tempfile ) { vlc_unlink( p_finder->p_sys->psz_tempfile ); FREENULL( p_finder->p_sys->psz_tempfile ); } p_finder->p_sys->psz_tempfile = tempnam( NULL, "vlp" ); if ( !p_finder->p_sys->psz_tempfile ) { msg_Err( p_finder, "Can't create temp storage file" ); vlc_stream_Delete( p_stream ); return VLC_EGENERIC; } FILE *p_destfile = vlc_fopen( p_finder->p_sys->psz_tempfile, "w" ); if( !p_destfile ) { msg_Err( p_finder, "Failed to open addon temp storage file" ); FREENULL(p_finder->p_sys->psz_tempfile); vlc_stream_Delete( p_stream ); return VLC_EGENERIC; } char buffer[1<<10]; int i_read = 0; while ( ( i_read = vlc_stream_Read( p_stream, &buffer, 1<<10 ) ) > 0 ) { if ( fwrite( &buffer, i_read, 1, p_destfile ) < 1 ) { msg_Err( p_finder, "Failed to write to Addon file" ); fclose( p_destfile ); vlc_stream_Delete( p_stream ); return VLC_EGENERIC; } } fclose( p_destfile ); vlc_stream_Delete( p_stream ); msg_Dbg( p_finder, "Reading manifest from %s", p_finder->p_sys->psz_tempfile ); char *psz_tempfileuri = vlc_path2uri( p_finder->p_sys->psz_tempfile, NULL ); if ( !psz_tempfileuri ) return VLC_ENOMEM; char *psz_manifest_uri; if ( asprintf( &psz_manifest_uri, "%s#!/manifest.xml", psz_tempfileuri ) < 1 ) { free( psz_tempfileuri ); return VLC_ENOMEM; } p_stream = vlc_stream_NewMRL( p_finder, psz_manifest_uri ); free( psz_manifest_uri ); if ( !p_stream ) { free( psz_tempfileuri ); return VLC_EGENERIC; } vlc_mutex_lock( &p_entry->lock ); int i_ret = ( ParseManifest( p_finder, p_entry, psz_tempfileuri, p_stream ) > 0 ) ? VLC_SUCCESS : VLC_EGENERIC; vlc_mutex_unlock( &p_entry->lock ); free( psz_tempfileuri ); vlc_stream_Delete( p_stream ); return i_ret; }
/** * Get the update file and parse it * p_update has to be locked when calling this function * * \param p_update pointer to update struct * \return true if the update is valid and authenticated */ static bool GetUpdateFile( update_t *p_update ) { stream_t *p_stream = NULL; char *psz_version_line = NULL; char *psz_update_data = NULL; p_stream = vlc_stream_NewURL( p_update->p_libvlc, UPDATE_VLC_STATUS_URL ); if( !p_stream ) { msg_Err( p_update->p_libvlc, "Failed to open %s for reading", UPDATE_VLC_STATUS_URL ); goto error; } uint64_t i_read; if( vlc_stream_GetSize( p_stream, &i_read ) || i_read >= UINT16_MAX ) { msg_Err(p_update->p_libvlc, "Status file too large"); goto error; } psz_update_data = malloc( i_read + 1 ); /* terminating '\0' */ if( !psz_update_data ) goto error; if( vlc_stream_Read( p_stream, psz_update_data, i_read ) != (ssize_t)i_read ) { msg_Err( p_update->p_libvlc, "Couldn't download update file %s", UPDATE_VLC_STATUS_URL ); goto error; } psz_update_data[i_read] = '\0'; vlc_stream_Delete( p_stream ); p_stream = NULL; /* first line : version number */ char *psz_update_data_parser = psz_update_data; size_t i_len = strcspn( psz_update_data, "\r\n" ); psz_update_data_parser += i_len; while( *psz_update_data_parser == '\r' || *psz_update_data_parser == '\n' ) psz_update_data_parser++; if( !(psz_version_line = malloc( i_len + 1)) ) goto error; strncpy( psz_version_line, psz_update_data, i_len ); psz_version_line[i_len] = '\0'; p_update->release.i_extra = 0; int ret = sscanf( psz_version_line, "%i.%i.%i.%i", &p_update->release.i_major, &p_update->release.i_minor, &p_update->release.i_revision, &p_update->release.i_extra); if( ret != 3 && ret != 4 ) { msg_Err( p_update->p_libvlc, "Update version false formatted" ); goto error; } /* second line : URL */ i_len = strcspn( psz_update_data_parser, "\r\n" ); if( i_len == 0 ) { msg_Err( p_update->p_libvlc, "Update file %s is corrupted: URL missing", UPDATE_VLC_STATUS_URL ); goto error; } if( !(p_update->release.psz_url = malloc( i_len + 1)) ) goto error; strncpy( p_update->release.psz_url, psz_update_data_parser, i_len ); p_update->release.psz_url[i_len] = '\0'; psz_update_data_parser += i_len; while( *psz_update_data_parser == '\r' || *psz_update_data_parser == '\n' ) psz_update_data_parser++; /* Remaining data : description */ i_len = strlen( psz_update_data_parser ); if( i_len == 0 ) { msg_Err( p_update->p_libvlc, "Update file %s is corrupted: description missing", UPDATE_VLC_STATUS_URL ); goto error; } if( !(p_update->release.psz_desc = malloc( i_len + 1)) ) goto error; strncpy( p_update->release.psz_desc, psz_update_data_parser, i_len ); p_update->release.psz_desc[i_len] = '\0'; /* Now that we know the status is valid, we must download its signature * to authenticate it */ signature_packet_t sign; if( download_signature( VLC_OBJECT( p_update->p_libvlc ), &sign, UPDATE_VLC_STATUS_URL ) != VLC_SUCCESS ) { msg_Err( p_update->p_libvlc, "Couldn't download signature of status file" ); goto error; } if( sign.type != BINARY_SIGNATURE && sign.type != TEXT_SIGNATURE ) { msg_Err( p_update->p_libvlc, "Invalid signature type" ); goto error; } p_update->p_pkey = (public_key_t*)malloc( sizeof( public_key_t ) ); if( !p_update->p_pkey ) goto error; if( parse_public_key( videolan_public_key, sizeof( videolan_public_key ), p_update->p_pkey, NULL ) != VLC_SUCCESS ) { msg_Err( p_update->p_libvlc, "Couldn't parse embedded public key, something went really wrong..." ); FREENULL( p_update->p_pkey ); goto error; } memcpy( p_update->p_pkey->longid, videolan_public_key_longid, 8 ); if( memcmp( sign.issuer_longid, p_update->p_pkey->longid , 8 ) != 0 ) { msg_Dbg( p_update->p_libvlc, "Need to download the GPG key" ); public_key_t *p_new_pkey = download_key( VLC_OBJECT(p_update->p_libvlc), sign.issuer_longid, videolan_public_key_longid ); if( !p_new_pkey ) { msg_Err( p_update->p_libvlc, "Couldn't download GPG key" ); FREENULL( p_update->p_pkey ); goto error; } uint8_t *p_hash = hash_from_public_key( p_new_pkey ); if( !p_hash ) { msg_Err( p_update->p_libvlc, "Failed to hash signature" ); free( p_new_pkey ); FREENULL( p_update->p_pkey ); goto error; } if( verify_signature( &p_new_pkey->sig, &p_update->p_pkey->key, p_hash ) == VLC_SUCCESS ) { free( p_hash ); msg_Info( p_update->p_libvlc, "Key authenticated" ); free( p_update->p_pkey ); p_update->p_pkey = p_new_pkey; } else { free( p_hash ); msg_Err( p_update->p_libvlc, "Key signature invalid !" ); goto error; } } uint8_t *p_hash = hash_from_text( psz_update_data, &sign ); if( !p_hash ) { msg_Warn( p_update->p_libvlc, "Can't compute hash for status file" ); goto error; } else if( p_hash[0] != sign.hash_verification[0] || p_hash[1] != sign.hash_verification[1] ) { msg_Warn( p_update->p_libvlc, "Bad hash for status file" ); free( p_hash ); goto error; } else if( verify_signature( &sign, &p_update->p_pkey->key, p_hash ) != VLC_SUCCESS ) { msg_Err( p_update->p_libvlc, "BAD SIGNATURE for status file" ); free( p_hash ); goto error; } else { msg_Info( p_update->p_libvlc, "Status file authenticated" ); free( p_hash ); free( psz_version_line ); free( psz_update_data ); return true; } error: if( p_stream ) vlc_stream_Delete( p_stream ); free( psz_version_line ); free( psz_update_data ); return false; }
/***************************************************************************** * Handshake : Init audioscrobbler connection *****************************************************************************/ static int Handshake(intf_thread_t *p_this) { char *psz_username, *psz_password; char *psz_scrobbler_url; time_t timestamp; char psz_timestamp[21]; struct md5_s p_struct_md5; stream_t *p_stream; char *psz_handshake_url; uint8_t p_buffer[1024]; char *p_buffer_pos; int i_ret; char *psz_url; intf_thread_t *p_intf = (intf_thread_t*) p_this; intf_sys_t *p_sys = p_this->p_sys; psz_username = var_InheritString(p_this, "lastfm-username"); psz_password = var_InheritString(p_this, "lastfm-password"); /* username or password have not been setup */ if (EMPTY_STR(psz_username) || EMPTY_STR(psz_password)) { free(psz_username); free(psz_password); return VLC_ENOVAR; } time(×tamp); /* generates a md5 hash of the password */ InitMD5(&p_struct_md5); AddMD5(&p_struct_md5, (uint8_t*) psz_password, strlen(psz_password)); EndMD5(&p_struct_md5); free(psz_password); char *psz_password_md5 = psz_md5_hash(&p_struct_md5); if (!psz_password_md5) { free(psz_username); return VLC_ENOMEM; } snprintf(psz_timestamp, sizeof(psz_timestamp), "%"PRIu64, (uint64_t)timestamp); /* generates a md5 hash of : * - md5 hash of the password, plus * - timestamp in clear text */ InitMD5(&p_struct_md5); AddMD5(&p_struct_md5, (uint8_t*) psz_password_md5, 32); AddMD5(&p_struct_md5, (uint8_t*) psz_timestamp, strlen(psz_timestamp)); EndMD5(&p_struct_md5); free(psz_password_md5); char *psz_auth_token = psz_md5_hash(&p_struct_md5); if (!psz_auth_token) { free(psz_username); return VLC_ENOMEM; } psz_scrobbler_url = var_InheritString(p_this, "scrobbler-url"); if (!psz_scrobbler_url) { free(psz_auth_token); free(psz_username); return VLC_ENOMEM; } i_ret = asprintf(&psz_handshake_url, "http://%s/?hs=true&p=1.2&c="CLIENT_NAME"&v="CLIENT_VERSION"&u=%s&t=%s&a=%s" , psz_scrobbler_url, psz_username, psz_timestamp, psz_auth_token); free(psz_auth_token); free(psz_scrobbler_url); free(psz_username); if (i_ret == -1) return VLC_ENOMEM; /* send the http handshake request */ p_stream = vlc_stream_NewURL(p_intf, psz_handshake_url); free(psz_handshake_url); if (!p_stream) return VLC_EGENERIC; /* read answer */ i_ret = vlc_stream_Read(p_stream, p_buffer, sizeof(p_buffer) - 1); if (i_ret <= 0) { vlc_stream_Delete(p_stream); return VLC_EGENERIC; } p_buffer[i_ret] = '\0'; vlc_stream_Delete(p_stream); p_buffer_pos = strstr((char*) p_buffer, "FAILED "); if (p_buffer_pos) { /* handshake request failed, sorry */ msg_Err(p_this, "last.fm handshake failed: %s", p_buffer_pos + 7); return VLC_EGENERIC; } if (strstr((char*) p_buffer, "BADAUTH")) { /* authentication failed, bad username/password combination */ vlc_dialog_display_error(p_this, _("last.fm: Authentication failed"), "%s", _("last.fm username or password is incorrect. " "Please verify your settings and relaunch VLC.")); return VLC_AUDIOSCROBBLER_EFATAL; } if (strstr((char*) p_buffer, "BANNED")) { /* oops, our version of vlc has been banned by last.fm servers */ msg_Err(p_intf, "This version of VLC has been banned by last.fm. " "You should upgrade VLC, or disable the last.fm plugin."); return VLC_AUDIOSCROBBLER_EFATAL; } if (strstr((char*) p_buffer, "BADTIME")) { /* The system clock isn't good */ msg_Err(p_intf, "last.fm handshake failed because your clock is too " "much shifted. Please correct it, and relaunch VLC."); return VLC_AUDIOSCROBBLER_EFATAL; } p_buffer_pos = strstr((char*) p_buffer, "OK"); if (!p_buffer_pos) goto proto; p_buffer_pos = strstr(p_buffer_pos, "\n"); if (!p_buffer_pos || strlen(p_buffer_pos) < 33) goto proto; p_buffer_pos++; /* we skip the '\n' */ /* save the session ID */ memcpy(p_sys->psz_auth_token, p_buffer_pos, 32); p_sys->psz_auth_token[32] = '\0'; p_buffer_pos = strstr(p_buffer_pos, "http://"); if (!p_buffer_pos || strlen(p_buffer_pos) == 7) goto proto; /* We need to read the nowplaying url */ psz_url = strndup(p_buffer_pos, strcspn(p_buffer_pos, "\n")); if (!psz_url) goto oom; vlc_UrlParse(&p_sys->p_nowp_url, psz_url); free(psz_url); if (p_sys->p_nowp_url.psz_host == NULL || p_sys->p_nowp_url.i_port == 0) { vlc_UrlClean(&p_sys->p_nowp_url); goto proto; } p_buffer_pos += strcspn(p_buffer_pos, "\n"); p_buffer_pos = strstr(p_buffer_pos, "http://"); if (!p_buffer_pos || strlen(p_buffer_pos) == 7) goto proto; /* We need to read the submission url */ psz_url = strndup(p_buffer_pos, strcspn(p_buffer_pos, "\n")); if (!psz_url) goto oom; /* parse the submission url */ vlc_UrlParse(&p_sys->p_submit_url, psz_url); free(psz_url); if (p_sys->p_submit_url.psz_host == NULL || p_sys->p_submit_url.i_port == 0) { vlc_UrlClean(&p_sys->p_nowp_url); vlc_UrlClean(&p_sys->p_submit_url); goto proto; } return VLC_SUCCESS; oom: return VLC_ENOMEM; proto: msg_Err(p_intf, "Handshake: can't recognize server protocol"); return VLC_EGENERIC; }
int RarAccessOpen(vlc_object_t *object) { access_t *access = (access_t*)object; const char *name = strchr(access->psz_location, '|'); if (name == NULL) return VLC_EGENERIC; char *base = strndup(access->psz_location, name - access->psz_location); if (unlikely(base == NULL)) return VLC_ENOMEM; name++; vlc_uri_decode(base); stream_t *s = vlc_stream_NewMRL(access, base); if (!s || RarProbe(s)) goto error; struct { int filescount; rar_file_t **files; unsigned int i_nbvols; } newscheme = { 0, NULL, 0 }, oldscheme = { 0, NULL, 0 }, *p_scheme; if (RarParse(s, &newscheme.filescount, &newscheme.files, &newscheme.i_nbvols, false) || newscheme.filescount < 1 || newscheme.i_nbvols < 2 ) { /* We might want to lookup old naming scheme, could be a part1.rar,part1.r00 */ vlc_stream_Seek(s, 0); RarParse(s, &oldscheme.filescount, &oldscheme.files, &oldscheme.i_nbvols, true); } if (oldscheme.filescount >= newscheme.filescount && oldscheme.i_nbvols > newscheme.i_nbvols) { for (int i = 0; i < newscheme.filescount; i++) RarFileDelete(newscheme.files[i]); free(newscheme.files); p_scheme = &oldscheme; msg_Dbg(s, "using rar old naming for %d files nbvols %u", p_scheme->filescount, oldscheme.i_nbvols); } else if (newscheme.filescount) { for (int i = 0; i < oldscheme.filescount; i++) RarFileDelete(oldscheme.files[i]); free(oldscheme.files); p_scheme = &newscheme; msg_Dbg(s, "using rar new naming for %d files nbvols %u", p_scheme->filescount, oldscheme.i_nbvols); } else { msg_Info(s, "Invalid or unsupported RAR archive"); for (int i = 0; i < oldscheme.filescount; i++) RarFileDelete(oldscheme.files[i]); free(oldscheme.files); for (int i = 0; i < newscheme.filescount; i++) RarFileDelete(newscheme.files[i]); free(newscheme.files); goto error; } rar_file_t *file = NULL; for (int i = 0; i < p_scheme->filescount; i++) { if (!file && !strcmp(p_scheme->files[i]->name, name)) file = p_scheme->files[i]; else RarFileDelete(p_scheme->files[i]); } free(p_scheme->files); if (!file) goto error; access_sys_t *sys = access->p_sys = malloc(sizeof(*sys)); sys->s = s; sys->file = file; access->pf_read = Read; access->pf_block = NULL; access->pf_control = Control; access->pf_seek = Seek; rar_file_chunk_t dummy = { .mrl = base, }; sys->chunk = &dummy; Seek(access, 0); free(base); return VLC_SUCCESS; error: if (s) vlc_stream_Delete(s); free(base); return VLC_EGENERIC; }