Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/misc/addons/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 17 kB image not shown  

Quelle  vorepository.c   Sprache: C

 

/*****************************************************************************
 * vorepository.c : Videolan.org's Addons Lister
 *****************************************************************************
 * Copyright (C) 2014 VLC authors and VideoLAN
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


/*****************************************************************************
 * Preamble
 *****************************************************************************/


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <assert.h>
#include <fcntl.h>
#include <unistd.h>     /* write() */

#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_stream.h>
#include <vlc_stream_extractor.h>
#include <vlc_addons.h>
#include <vlc_xml.h>
#include <vlc_fs.h>
#include <vlc_url.h>
#include "xmlreading.h"

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/


static int   Open ( vlc_object_t * );
static void  Close ( vlc_object_t * );
static int   Retrieve ( addons_finder_t *p_finder, addon_entry_t *p_entry );
static int   OpenDesignated ( vlc_object_t * );
static int   FindDesignated ( addons_finder_t *p_finder );

#define ADDONS_MODULE_SHORTCUT "addons.vo"
#define ADDONS_REPO_SCHEMEHOST "https://api-addons.videolan.org"
/*****************************************************************************
 * Module descriptor
 ****************************************************************************/


vlc_module_begin ()
    set_subcategory(SUBCAT_ADVANCED_MISC)
    set_shortname(N_("Videolan.org's addons finder"))
    add_shortcut(ADDONS_MODULE_SHORTCUT)
    set_description(N_("addons.videolan.org addons finder"))
    set_capability("addons finder", 100)
    set_callbacks(Open, Close)
add_submodule ()
    set_subcategory(SUBCAT_ADVANCED_MISC)
    set_shortname(N_("Videolan.org's single archive addons finder"))
    add_shortcut(ADDONS_MODULE_SHORTCUT".vlp")
    set_description(N_("single .vlp archive addons finder"))
    set_capability("addons finder", 101)
    set_callback(OpenDesignated)
vlc_module_end ()

struct addons_finder_sys_t
{
    char *psz_tempfile;
};

static int ParseManifest( addons_finder_t *p_finder, addon_entry_t *p_entry,
                          const char *psz_tempfileuri, stream_t *p_stream )
{
    int i_num_entries_created = 0;
    const char *p_node;
    int i_current_node_type;

    /* attr */
    const char *attr, *value;

    /* temp reading */
    char *psz_filename = NULL;
    int i_filetype = -1;

    xml_reader_t *p_xml_reader = xml_ReaderCreate( p_finder, p_stream );
    if( !p_xml_reader ) return 0;

    if( xml_ReaderNextNode( p_xml_reader, &p_node ) != XML_READER_STARTELEM )
    {
        msg_Err( p_finder, "invalid xml file" );
        goto end;
    }

    if ( strcmp( p_node, "videolan") )
    {
        msg_Err( p_finder, "unsupported XML data format" );
        goto end;
    }

    while( (i_current_node_type = xml_ReaderNextNode( p_xml_reader, &p_node )) > 0 )
    {
        switch( i_current_node_type )
        {
        case XML_READER_STARTELEM:
        {
            BINDNODE("resource", psz_filename, TYPE_STRING)
            data_pointer.e_type = TYPE_NONE;

            /*
             * Manifests are not allowed to update addons properties
             * such as uuid, score, downloads, ...
             * On the other hand, repo API must not set files directly.
             */


            if ( ! strcmp( p_node, "resource" ) )
            {
                while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) )
                {
                    if ( !strcmp( attr, "type" ) )
                    {
                        i_filetype = ReadType( value );
                    }
                }
            }
            else if ( ! strcmp( p_node, "addon" ) )
            {
                while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) )
                {
                    if ( !strcmp( attr, "type" ) )
                    {
                        p_entry->e_type = ReadType( value );
                    }
                }
            }

            break;
        }
        case XML_READER_TEXT:
            if ( data_pointer.e_type == TYPE_NONE || !p_entry ) break;
            if ( data_pointer.e_type == TYPE_STRING )
            {
                if( data_pointer.u_data.ppsz )
                    free( *data_pointer.u_data.ppsz );
                *data_pointer.u_data.ppsz = strdup( p_node );
            }
            else
            if ( data_pointer.e_type == TYPE_LONG )
                *data_pointer.u_data.pl = atol( p_node );
            else
            if ( data_pointer.e_type == TYPE_INTEGER )
                *data_pointer.u_data.pi = atoi( p_node );
            break;

        case XML_READER_ENDELEM:

            if ( ! strcmp( p_node, "resource" ) )
            {
                if ( psz_filename && i_filetype >= 0 )
                {
                    addon_file_t *p_file = malloc( sizeof(addon_file_t) );
                    p_file->e_filetype = i_filetype;
                    p_file->psz_filename = strdup( psz_filename );
                    if ( asprintf( & p_file->psz_download_uri, "%s#!/%s",
                                   psz_tempfileuri, psz_filename  ) > 0 )
                    {
                        ARRAY_APPEND( p_entry->files, p_file );
                        msg_Dbg( p_finder, "manifest lists file %s extractable from %s",
                                 psz_filename, p_file->psz_download_uri );
                        i_num_entries_created++;
                    }
                    else
                    {
                        free( p_file->psz_filename );
                        free( p_file );
                    }
                }
                /* reset temp */
                free( psz_filename );
                psz_filename = NULL;
                i_filetype = -1;
            }

            data_pointer.e_type = TYPE_NONE;
            break;

        default:
            break;
        }
    }

end:
   xml_ReaderDelete( p_xml_reader );
   return i_num_entries_created;
}

static int ParseCategoriesInfo( addons_finder_t *p_finder, stream_t *p_stream )
{
    int i_num_entries_created = 0;

    const char *p_node;
    const char *attr, *value;
    int i_current_node_type;
    addon_entry_t *p_entry = NULL;

    xml_reader_t *p_xml_reader = xml_ReaderCreate( p_finder, p_stream );
    if( !p_xml_reader ) return 0;

    if( xml_ReaderNextNode( p_xml_reader, &p_node ) != XML_READER_STARTELEM )
    {
        msg_Err( p_finder, "invalid xml file" );
        goto end;
    }

    if ( strcmp( p_node, "videolan") )
    {
        msg_Err( p_finder, "unsupported XML data format" );
        goto end;
    }

    while( (i_current_node_type = xml_ReaderNextNode( p_xml_reader, &p_node )) > 0 )
    {
        switch( i_current_node_type )
        {
        case XML_READER_STARTELEM:
        {
            if ( ! strcmp( p_node, "addon" ) )
            {
                if ( p_entry ) /* Unclosed tag */
                    addon_entry_Release( p_entry );
                p_entry = addon_entry_New();
                p_entry->psz_source_module = strdup( ADDONS_MODULE_SHORTCUT );
                p_entry->e_flags = ADDON_MANAGEABLE;
                p_entry->e_state = ADDON_NOTINSTALLED;

                while( (attr = xml_ReaderNextAttr( p_xml_reader, &value )) )
                {
                    if ( !strcmp( attr, "type" ) )
                    {
                        p_entry->e_type = ReadType( value );
                    }
                    else if ( !strcmp( attr, "id" ) )
                    {
                        addons_uuid_read( value, & p_entry->uuid );
                    }
                    else if ( !strcmp( attr, "downloads" ) )
                    {
                        p_entry->i_downloads = atoi( value );
                        if ( p_entry->i_downloads < 0 )
                            p_entry->i_downloads = 0;
                    }
                    else if ( !strcmp( attr, "score" ) )
                    {
                        p_entry->i_score = atoi( value );
                        if ( p_entry->i_score < 0 )
                            p_entry->i_score = 0;
                        else if ( p_entry->i_score > ADDON_MAX_SCORE )
                            p_entry->i_score = ADDON_MAX_SCORE;
                    }
                    else if ( !strcmp( attr, "version" ) )
                    {
                        p_entry->psz_version = strdup( value );
                    }
                }

                break;
            }
            if ( !p_entry ) break;

            BINDNODE("name", p_entry->psz_name, TYPE_STRING)
            BINDNODE("archive", p_entry->psz_archive_uri, TYPE_STRING)
            BINDNODE("summary", p_entry->psz_summary, TYPE_STRING)
            BINDNODE("description", p_entry->psz_description, TYPE_STRING)
            BINDNODE("image", p_entry->psz_image_data, TYPE_STRING)
            BINDNODE("creator", p_entry->psz_author, TYPE_STRING)
            BINDNODE("sourceurl", p_entry->psz_source_uri, TYPE_STRING)
            data_pointer.e_type = TYPE_NONE;

            break;
        }
        case XML_READER_TEXT:
            if ( data_pointer.e_type == TYPE_NONE || !p_entry ) break;
            if ( data_pointer.e_type == TYPE_STRING )
            {
                if( data_pointer.u_data.ppsz )
                    free( *data_pointer.u_data.ppsz );
                *data_pointer.u_data.ppsz = strdup( p_node );
            }
            else
            if ( data_pointer.e_type == TYPE_LONG )
                *data_pointer.u_data.pl = atol( p_node );
            else
            if ( data_pointer.e_type == TYPE_INTEGER )
                *data_pointer.u_data.pi = atoi( p_node );
            break;

        case XML_READER_ENDELEM:
            if ( !p_entry ) break;
            if ( ! strcmp( p_node, "addon" ) )
            {
                /* then append entry */
                ARRAY_APPEND( p_finder->entries, p_entry );
                p_entry = NULL;
                i_num_entries_created++;
            }

            data_pointer.e_type = TYPE_NONE;
            break;

        default:
            break;
        }
    }

end:
   if ( p_entry ) /* Unclosed tag */
       addon_entry_Release( p_entry );
   xml_ReaderDelete( p_xml_reader );
   return i_num_entries_created;
}

static stream_t * vlc_stream_NewURL_ND( addons_finder_t *p_obj, const char *psz_uri )
{
    stream_t *p_stream = vlc_stream_NewURL( p_obj, psz_uri );
    if( p_stream )
    {
        /* (non applicable everywhere) remove extra
         * compression, bad wine madness :YYY */

        stream_t *p_chain = vlc_stream_FilterNew( p_stream, "inflate" );
        if( p_chain )
            p_stream = p_chain;
    }
    return p_stream;
}

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 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 ) == -1 )
        {
            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;
    }

    int fd = vlc_open( p_finder->p_sys->psz_tempfile,
                       O_WRONLY | O_CREAT | O_EXCL, 0600 );
    if( fd == -1 )
    {
        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];
    ssize_t i_read = 0;
    int i_ret = VLC_SUCCESS;

    while ( ( i_read = vlc_stream_Read( p_stream, &buffer, 1<<10 ) ) > 0 )
    {
        if ( write( fd, buffer, i_read ) != i_read )
        {
            msg_Err( p_finder, "Failed to write to Addon file" );
            i_ret = VLC_EGENERIC;
            break;
        }
    }

    vlc_close( fd );
    vlc_stream_Delete( p_stream );

    if (i_ret)
        return i_ret;

    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 );
    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;
}

static int FindDesignated( addons_finder_t *p_finder )
{
    char *psz_manifest;
    const char *psz_path = p_finder->psz_uri + 7; // remove scheme

    if ( asprintf( &psz_manifest, "file://%s#!/manifest.xml",
                   psz_path ) < 1 )
        return VLC_ENOMEM;

    stream_t *p_stream = vlc_stream_NewMRL( p_finder, psz_manifest );
    free( psz_manifest );
    if ( !p_stream ) return VLC_EGENERIC;

    if ( ParseCategoriesInfo( p_finder, p_stream ) )
    {
        /* Do archive uri fixup */
        addon_entry_t *p_entry;
        ARRAY_FOREACH( p_entry, p_finder->entries )
            if ( likely( !p_entry->psz_archive_uri ) )
                p_entry->psz_archive_uri = strdup( p_finder->psz_uri );
    }
    else
    {
        vlc_stream_Delete( p_stream );
        return VLC_EGENERIC;
    }

    vlc_stream_Delete( p_stream );

    return VLC_SUCCESS;
}

static int Open(vlc_object_t *p_this)
{
    addons_finder_t *p_finder = (addons_finder_t*) p_this;

    p_finder->p_sys = (addons_finder_sys_t*) malloc(sizeof(addons_finder_sys_t));
    if ( !p_finder->p_sys )
        return VLC_ENOMEM;
    p_finder->p_sys->psz_tempfile = NULL;

    if ( p_finder->psz_uri &&
         strcmp( "repo://"ADDONS_MODULE_SHORTCUT, p_finder->psz_uri ) &&
         memcmp( "repo://", p_finder->psz_uri, 8 ) )
    {
        free( p_finder->p_sys );
        return VLC_EGENERIC;
    }

    p_finder->pf_find = Find;
    p_finder->pf_retrieve = Retrieve;

    return VLC_SUCCESS;
}

static void Close(vlc_object_t *p_this)
{
    addons_finder_t *p_finder = (addons_finder_t*) p_this;
    if ( p_finder->p_sys->psz_tempfile )
    {
        vlc_unlink( p_finder->p_sys->psz_tempfile );
        free( p_finder->p_sys->psz_tempfile );
    }
    free( p_finder->p_sys );
}

static int OpenDesignated(vlc_object_t *p_this)
{
    addons_finder_t *p_finder = (addons_finder_t*) p_this;
    if ( !p_finder->psz_uri
         || strncmp( "file://", p_finder->psz_uri, 7 )
         || strncmp( ".vlp", p_finder->psz_uri + strlen( p_finder->psz_uri ) - 4, 4 )
       )
        return VLC_EGENERIC;

    p_finder->pf_find = FindDesignated;
    p_finder->pf_retrieve = Retrieve;

    return VLC_SUCCESS;
}

Messung
CHZG
829610092

¤ Dauer der Verarbeitung: 0.8 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.