themeloader.cpp

来自「VLC媒体播放程序」· C++ 代码 · 共 494 行

CPP
494
字号
/***************************************************************************** * themeloader.cpp: ThemeLoader class ***************************************************************************** * Copyright (C) 2003 VideoLAN * $Id: themeloader.cpp,v 1.16 2003/12/16 18:18:14 gbazin Exp $ * * Authors: Olivier Teuli鑢e <ipkiss@via.ecp.fr> *          Emmanuel Puig    <karibu@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, * USA. *****************************************************************************///--- GENERAL ---------------------------------------------------------------#include <string>#include <fcntl.h>#if !defined( WIN32 )#   include <unistd.h>#else#   include <direct.h>#   ifndef PATH_MAX#       define PATH_MAX MAX_PATH#   endif#endif//--- VLC -------------------------------------------------------------------#include <vlc/vlc.h>#include <vlc/intf.h>#if defined( HAVE_ZLIB_H )#   include <zlib.h>#   include <errno.h>#endif#if defined( HAVE_ZLIB_H ) && defined( HAVE_LIBTAR_H )#   include <libtar.h>#elif defined( HAVE_ZLIB_H )    typedef gzFile TAR;    int tar_open         ( TAR **t, char *pathname, int oflags );    int tar_extract_all  ( TAR *t, char *prefix );    int tar_close        ( TAR *t );#endif//--- SKIN ------------------------------------------------------------------#include "../os_api.h"#include "theme.h"#include "../os_theme.h"#include "themeloader.h"#include "skin_common.h"#include "anchor.h"#include "window.h"#define DEFAULT_XML_FILE "theme.xml"//---------------------------------------------------------------------------extern "C"{    extern FILE *yyin;    int yylex();}//---------------------------------------------------------------------------ThemeLoader::ThemeLoader( intf_thread_t *_p_intf ){    p_intf = _p_intf;}//---------------------------------------------------------------------------ThemeLoader::~ThemeLoader(){}//---------------------------------------------------------------------------#if defined( HAVE_ZLIB_H )int gzopen_frontend( char *pathname, int oflags, int mode ){    char *gzflags;    gzFile gzf;    switch( oflags & O_ACCMODE )    {        case O_WRONLY:            gzflags = "wb";            break;        case O_RDONLY:            gzflags = "rb";            break;        case O_RDWR:        default:            errno = EINVAL;            return -1;    }    gzf = gzopen( pathname, gzflags );    if( !gzf )    {        errno = ENOMEM;        return -1;    }    return (int)gzf;}#endif//---------------------------------------------------------------------------#if defined( HAVE_ZLIB_H )bool ThemeLoader::ExtractTarGz( const string tarfile, const string rootdir ){    TAR *t;#if defined( HAVE_LIBTAR_H )    tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose,        (readfunc_t) gzread, (writefunc_t) gzwrite };    if( tar_open( &t, (char *)tarfile.c_str(), &gztype, O_RDONLY, 0,                  TAR_GNU ) == -1 )#else    if( tar_open( &t, (char *)tarfile.c_str(), O_RDONLY ) == -1 )#endif    {        return false;    }    if( tar_extract_all( t, (char *)rootdir.c_str() ) != 0 )    {   tar_close( t );        return false;    }    if( tar_close( t ) != 0 )    {        return false;    }    return true;}//---------------------------------------------------------------------------bool ThemeLoader::Extract( const string FileName ){    char *tmpdir = tempnam( NULL, "vlt" );    string TempPath = tmpdir;    free( tmpdir );    if( ! ExtractTarGz( FileName, TempPath ) )        return false;    if( ! Parse( TempPath + DIRECTORY_SEPARATOR + string( DEFAULT_XML_FILE ) ) )    {        msg_Err( p_intf, "%s doesn't contain a " DEFAULT_XML_FILE " file",                 FileName.c_str() );        DeleteTempFiles( TempPath );        return false;    }    DeleteTempFiles( TempPath );    return true;}//---------------------------------------------------------------------------void ThemeLoader::DeleteTempFiles( const string Path ){    OSAPI_RmDir( Path );}#endif//---------------------------------------------------------------------------void ThemeLoader::CleanTheme(){    delete (OSTheme *)p_intf->p_sys->p_theme;    p_intf->p_sys->p_theme = (Theme *)new OSTheme( p_intf );}//---------------------------------------------------------------------------bool ThemeLoader::Parse( const string XmlFile ){    // Things to do before loading theme    p_intf->p_sys->p_theme->OnLoadTheme();    // Set the file to parse    yyin = fopen( XmlFile.c_str(), "r" );    if( yyin == NULL )    {        // Skin cannot be opened        msg_Warn( p_intf, "Cannot open the specified skin file: %s",                  XmlFile.c_str() );        return false;    }    // File loaded    msg_Dbg( p_intf, "Using skin file: %s", XmlFile.c_str() );    // Save current working directory    char *cwd = new char[PATH_MAX];    getcwd( cwd, PATH_MAX );    // Directory separator is different in each OS !    int p = XmlFile.rfind( DIRECTORY_SEPARATOR, XmlFile.size() );    // Change current working directory to xml file    string path = "";    if( p > 0 )        path = XmlFile.substr( 0, p );    chdir( path.c_str() );    p_intf->p_sys->b_all_win_closed = false;    // Start the parser    int lex = yylex();        fclose( yyin );    if( lex )    {        // Set old working directory to current        chdir( cwd );        delete[] cwd;        msg_Warn( p_intf, "yylex failed: %i", lex );        CleanTheme();        return false;    }    // Set old working directory to current    chdir( cwd );    delete[] cwd;    return true;}//---------------------------------------------------------------------------bool ThemeLoader::Load( const string FileName ){    // First, we try to un-targz the file, and if it fails we hope it's a XML    // file...#if defined( HAVE_ZLIB_H )    if( ! Extract( FileName ) && ! Parse( FileName ) )        return false;#else    if( ! Parse( FileName ) )        return false;#endif    // Check if the skin to load is in the config file, to load its config    char *skin_last = config_GetPsz( p_intf, "skin_last" );    if( skin_last != NULL && FileName == (string)skin_last )    {        p_intf->p_sys->p_theme->LoadConfig();    }    else    {        config_PutPsz( p_intf, "skin_last", FileName.c_str() );        config_SaveConfigFile( p_intf, "skins" );    }    return true;}//---------------------------------------------------------------------------#if !defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )#ifdef WIN32#  define mkdir(dirname,mode) _mkdir(dirname)#endif/* Values used in typeflag field.  */#define REGTYPE  '0'            /* regular file */#define AREGTYPE '\0'           /* regular file */#define DIRTYPE  '5'            /* directory */#define BLOCKSIZE 512struct tar_header{                               /* byte offset */  char name[100];               /*   0 */  char mode[8];                 /* 100 */  char uid[8];                  /* 108 */  char gid[8];                  /* 116 */  char size[12];                /* 124 */  char mtime[12];               /* 136 */  char chksum[8];               /* 148 */  char typeflag;                /* 156 */  char linkname[100];           /* 157 */  char magic[6];                /* 257 */  char version[2];              /* 263 */  char uname[32];               /* 265 */  char gname[32];               /* 297 */  char devmajor[8];             /* 329 */  char devminor[8];             /* 337 */  char prefix[155];             /* 345 */                                /* 500 */};union tar_buffer {  char               buffer[BLOCKSIZE];  struct tar_header  header;};/* helper functions */int getoct( char *p, int width );int makedir( char *newdir );int tar_open( TAR **t, char *pathname, int oflags ){    gzFile f = gzopen( pathname, "rb" );    if( f == NULL )    {        //fprintf( stderr, "Couldn't gzopen %s\n", pathname );        return -1;    }    *t = (gzFile *)malloc( sizeof(gzFile) );    **t = f;    return 0;}int tar_extract_all( TAR *t, char *prefix ){    union  tar_buffer buffer;    int    len, err, getheader = 1, remaining = 0;    FILE   *outfile = NULL;    char   fname[BLOCKSIZE + PATH_MAX];    while( 1 )    {        len = gzread( *t, &buffer, BLOCKSIZE );        if(len < 0) fprintf(stderr, "%s\n", gzerror(*t, &err) );        /*         * Always expect complete blocks to process         * the tar information.         */        if( len != 0 && len != BLOCKSIZE )        {            fprintf(stderr, "gzread: incomplete block read\n");            return -1;        }        /*         * If we have to get a tar header         */        if( getheader == 1 )        {            /*             * if we met the end of the tar             * or the end-of-tar block,             * we are done             */            if( (len == 0)  || (buffer.header.name[0]== 0) ) break;            sprintf( fname, "%s/%s", prefix, buffer.header.name );            /* Check magic value in header */            if( strncmp( buffer.header.magic, "GNUtar", 6 ) &&                strncmp( buffer.header.magic, "ustar", 5 ) )            {                //fprintf(stderr, "not a tar file\n");                return -1;            }            switch (buffer.header.typeflag)            {            case DIRTYPE:                makedir( fname );                break;            case REGTYPE:            case AREGTYPE:                remaining = getoct( buffer.header.size, 12 );                if( remaining )                {                    outfile = fopen( fname, "wb" );                    if( outfile == NULL )                    {                        /* try creating directory */                        char *p = strrchr( fname, '/' );                        if( p != NULL )                        {                            *p = '\0';                            makedir( fname );                            *p = '/';                            outfile = fopen( fname, "wb" );                            if( !outfile )                                fprintf( stderr, "tar couldn't create %s\n",                                         fname );                        }                    }                }                else outfile = NULL;                /*                 * could have no contents                 */                getheader = (remaining) ? 0 : 1;                break;            default:                break;            }        }        else        {            unsigned int bytes = (remaining > BLOCKSIZE)?BLOCKSIZE:remaining;            if( outfile != NULL )            {                if( fwrite( &buffer, sizeof(char), bytes, outfile ) != bytes )                {                    fprintf( stderr, "error writing %s skipping...\n", fname );                    fclose( outfile );                    unlink( fname );                }            }            remaining -= bytes;            if( remaining == 0 )            {                getheader = 1;                if( outfile != NULL )                {                    fclose(outfile);                    outfile = NULL;                }            }        }    }    return 0;}int tar_close( TAR *t ){    if( gzclose( *t ) != Z_OK ) fprintf( stderr, "failed gzclose\n" );    free( t );    return 0;}/* helper functions */int getoct( char *p, int width ){    int result = 0;    char c;      while( width-- )    {        c = *p++;        if (c == ' ') continue;        if (c == 0) break;        result = result * 8 + (c - '0');    }    return result;}/* Recursive make directory * Abort if you get an ENOENT errno somewhere in the middle * e.g. ignore error "mkdir on existing directory" * * return 1 if OK, 0 on error */int makedir( char *newdir ){    char *p, *buffer = strdup(newdir);    int  len = strlen(buffer);      if( len <= 0 ) { free(buffer); return 0; }    if( buffer[len-1] == '/' ) buffer[len-1] = '\0';    if( mkdir( buffer, 0775 ) == 0 ) { free(buffer); return 1; }    p = buffer+1;    while( 1 )    {        char hold;        while( *p && *p != '\\' && *p != '/' ) p++;        hold = *p;        *p = 0;        if( ( mkdir( buffer, 0775 ) == -1 ) && ( errno == ENOENT ) )        {            fprintf(stderr,"couldn't create directory %s\n", buffer);            free(buffer);            return 0;        }        if( hold == 0 ) break;        *p++ = hold;    }    free(buffer);    return 1;}#endif//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?