theme_loader.cpp
资源名称:vlc-1.0.5.zip [点击查看]
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:20k
源码类别:
midi
开发平台:
Unix_Linux
- /*****************************************************************************
- * theme_loader.cpp
- *****************************************************************************
- * Copyright (C) 2003 the VideoLAN team
- * $Id: d02fa718e1a777bb7c07b658631bd97ea93ba080 $
- *
- * Authors: Cyril Deguet <asmax@via.ecp.fr>
- * Olivier Teulière <ipkiss@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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
- #include "theme_loader.hpp"
- #include "theme.hpp"
- #include "../parser/builder.hpp"
- #include "../parser/skin_parser.hpp"
- #include "../src/os_factory.hpp"
- #include "../src/vlcproc.hpp"
- #include "../src/window_manager.hpp"
- #include <cctype>
- #ifdef HAVE_FCNTL_H
- # include <fcntl.h>
- #endif
- #ifdef HAVE_SYS_STAT_H
- # include <sys/stat.h>
- #endif
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #elif defined( WIN32 ) && !defined( UNDER_CE )
- # include <direct.h>
- #endif
- #ifdef HAVE_DIRENT_H
- # include <dirent.h>
- #endif
- #if defined( HAVE_ZLIB_H )
- # include <zlib.h>
- # include <errno.h>
- int gzopen_frontend ( const char *pathname, int oflags, int mode );
- int gzclose_frontend( int );
- int gzread_frontend ( int, void *, size_t );
- int gzwrite_frontend( int, const void *, size_t );
- #if defined( HAVE_LIBTAR_H )
- # include <libtar.h>
- #else
- 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 );
- int getoct( char *p, int width );
- #endif
- int makedir( const char *newdir );
- #endif
- #define DEFAULT_XML_FILE "theme.xml"
- #define WINAMP2_XML_FILE "winamp2.xml"
- #define ZIP_BUFFER_SIZE 4096
- bool ThemeLoader::load( const string &fileName )
- {
- string path = getFilePath( fileName );
- //Before all, let's see if the file is present
- struct stat p_stat;
- if( utf8_stat( path.c_str(), &p_stat ) )
- return false;
- // 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( sToLocale( fileName ) ) && ! parse( path, fileName ) )
- return false;
- #else
- if( ! parse( path, fileName ) )
- return false;
- #endif
- Theme *pNewTheme = getIntf()->p_sys->p_theme;
- if( !pNewTheme )
- {
- return false;
- }
- // Check if the skin to load is in the config file, to load its config
- char *skin_last = config_GetPsz( getIntf(), "skins2-last" );
- if( skin_last != NULL && fileName == (string)skin_last )
- {
- // Restore the theme configuration
- getIntf()->p_sys->p_theme->loadConfig();
- // Used to anchor the windows at the beginning
- pNewTheme->getWindowManager().stopMove();
- }
- else
- {
- config_PutPsz( getIntf(), "skins2-last", fileName.c_str() );
- // Show the windows
- pNewTheme->getWindowManager().showAll( true );
- }
- free( skin_last );
- return true;
- }
- #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_frontend,
- (readfunc_t) gzread_frontend,
- (writefunc_t) gzwrite_frontend };
- 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::extractZip( const string &zipFile, const string &rootDir )
- {
- // Try to open the ZIP file
- unzFile file = unzOpen( zipFile.c_str() );
- unz_global_info info;
- if( unzGetGlobalInfo( file, &info ) != UNZ_OK )
- {
- return false;
- }
- // Extract all the files in the archive
- for( unsigned long i = 0; i < info.number_entry; i++ )
- {
- if( !extractFileInZip( file, rootDir ) )
- {
- msg_Warn( getIntf(), "error while unzipping %s",
- zipFile.c_str() );
- unzClose( file );
- return false;
- }
- if( i < info.number_entry - 1 )
- {
- // Go the next file in the archive
- if( unzGoToNextFile( file ) !=UNZ_OK )
- {
- msg_Warn( getIntf(), "error while unzipping %s",
- zipFile.c_str() );
- unzClose( file );
- return false;
- }
- }
- }
- unzClose( file );
- return true;
- }
- bool ThemeLoader::extractFileInZip( unzFile file, const string &rootDir )
- {
- // Read info for the current file
- char filenameInZip[256];
- unz_file_info fileInfo;
- if( unzGetCurrentFileInfo( file, &fileInfo, filenameInZip,
- sizeof( filenameInZip), NULL, 0, NULL, 0 )
- != UNZ_OK )
- {
- return false;
- }
- #ifdef WIN32
- // Convert the file name to lower case, because some winamp skins
- // use the wrong case...
- for( size_t i=0; i< strlen( filenameInZip ); i++)
- {
- filenameInZip[i] = tolower( filenameInZip[i] );
- }
- #endif
- // Allocate the buffer
- void *pBuffer = malloc( ZIP_BUFFER_SIZE );
- if( !pBuffer )
- return false;
- // Get the path of the file
- OSFactory *pOsFactory = OSFactory::instance( getIntf() );
- string fullPath = rootDir
- + pOsFactory->getDirSeparator()
- + fixDirSeparators( filenameInZip );
- string basePath = getFilePath( fullPath );
- // Extract the file if is not a directory
- if( basePath != fullPath )
- {
- if( unzOpenCurrentFile( file ) )
- {
- free( pBuffer );
- return false;
- }
- makedir( basePath.c_str() );
- FILE *fout = fopen( fullPath.c_str(), "wb" );
- if( fout == NULL )
- {
- msg_Err( getIntf(), "error opening %s", fullPath.c_str() );
- free( pBuffer );
- return false;
- }
- // Extract the current file
- int n;
- do
- {
- n = unzReadCurrentFile( file, pBuffer, ZIP_BUFFER_SIZE );
- if( n < 0 )
- {
- msg_Err( getIntf(), "error while reading zip file" );
- free( pBuffer );
- return false;
- }
- else if( n > 0 )
- {
- if( fwrite( pBuffer, n , 1, fout) != 1 )
- {
- msg_Err( getIntf(), "error while writing %s",
- fullPath.c_str() );
- free( pBuffer );
- return false;
- }
- }
- } while( n > 0 );
- fclose(fout);
- if( unzCloseCurrentFile( file ) != UNZ_OK )
- {
- free( pBuffer );
- return false;
- }
- }
- free( pBuffer );
- return true;
- }
- bool ThemeLoader::extract( const string &fileName )
- {
- bool result = true;
- char *tmpdir = tempnam( NULL, "vlt" );
- string tempPath = sFromLocale( tmpdir );
- free( tmpdir );
- // Extract the file in a temporary directory
- if( ! extractTarGz( fileName, tempPath ) &&
- ! extractZip( fileName, tempPath ) )
- {
- deleteTempFiles( tempPath );
- return false;
- }
- string path;
- string xmlFile;
- OSFactory *pOsFactory = OSFactory::instance( getIntf() );
- // Find the XML file in the theme
- if( findFile( tempPath, DEFAULT_XML_FILE, xmlFile ) )
- {
- path = getFilePath( xmlFile );
- }
- else
- {
- // No XML file, check if it is a winamp2 skin
- string mainBmp;
- if( findFile( tempPath, "main.bmp", mainBmp ) )
- {
- msg_Dbg( getIntf(), "trying to load a winamp2 skin" );
- path = getFilePath( mainBmp );
- // Look for winamp2.xml in the resource path
- list<string> resPath = pOsFactory->getResourcePath();
- list<string>::const_iterator it;
- for( it = resPath.begin(); it != resPath.end(); it++ )
- {
- if( findFile( *it, WINAMP2_XML_FILE, xmlFile ) )
- break;
- }
- }
- }
- if( !xmlFile.empty() )
- {
- // Parse the XML file
- if (! parse( path, xmlFile ) )
- {
- msg_Err( getIntf(), "error while parsing %s", xmlFile.c_str() );
- result = false;
- }
- }
- else
- {
- msg_Err( getIntf(), "no XML found in theme %s", fileName.c_str() );
- result = false;
- }
- // Clean-up
- deleteTempFiles( tempPath );
- return result;
- }
- void ThemeLoader::deleteTempFiles( const string &path )
- {
- OSFactory::instance( getIntf() )->rmDir( path );
- }
- #endif // HAVE_ZLIB_H
- bool ThemeLoader::parse( const string &path, const string &xmlFile )
- {
- // File loaded
- msg_Dbg( getIntf(), "using skin file: %s", xmlFile.c_str() );
- // Start the parser
- SkinParser parser( getIntf(), xmlFile, path );
- if( ! parser.parse() )
- return false;
- // Build and store the theme
- Builder builder( getIntf(), parser.getData(), path );
- getIntf()->p_sys->p_theme = builder.build();
- return true;
- }
- string ThemeLoader::getFilePath( const string &rFullPath )
- {
- OSFactory *pOsFactory = OSFactory::instance( getIntf() );
- const string &sep = pOsFactory->getDirSeparator();
- // Find the last separator ('/' or '')
- string::size_type p = rFullPath.rfind( sep, rFullPath.size() );
- string basePath;
- if( p != string::npos )
- {
- if( p < rFullPath.size() - 1)
- {
- basePath = rFullPath.substr( 0, p );
- }
- else
- {
- basePath = rFullPath;
- }
- }
- return basePath;
- }
- string ThemeLoader::fixDirSeparators( const string &rPath )
- {
- OSFactory *pOsFactory = OSFactory::instance( getIntf() );
- const string &sep = pOsFactory->getDirSeparator();
- string::size_type p = rPath.find( "/", 0 );
- string newPath = rPath;
- while( p != string::npos )
- {
- newPath = newPath.replace( p, 1, sep );
- p = newPath.find( "/", p + 1 );
- }
- return newPath;
- }
- bool ThemeLoader::findFile( const string &rootDir, const string &rFileName,
- string &themeFilePath )
- {
- // Path separator
- const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
- DIR *pCurrDir;
- char *pszDirContent;
- // Open the dir
- pCurrDir = utf8_opendir( rootDir.c_str() );
- if( pCurrDir == NULL )
- {
- // An error occurred
- msg_Dbg( getIntf(), "cannot open directory %s", rootDir.c_str() );
- return false;
- }
- // While we still have entries in the directory
- while( ( pszDirContent = utf8_readdir( pCurrDir ) ) != NULL )
- {
- string newURI = rootDir + sep + pszDirContent;
- // Skip . and ..
- if( string( pszDirContent ) != "." &&
- string( pszDirContent ) != ".." )
- {
- #if defined( S_ISDIR )
- struct stat stat_data;
- if( ( utf8_stat( newURI.c_str(), &stat_data ) == 0 )
- && S_ISDIR(stat_data.st_mode) )
- #elif defined( DT_DIR )
- if( pDirContent->d_type & DT_DIR )
- #else
- if( 0 )
- #endif
- {
- // Can we find the file in this subdirectory?
- if( findFile( newURI, rFileName, themeFilePath ) )
- {
- free( pszDirContent );
- closedir( pCurrDir );
- return true;
- }
- }
- else
- {
- // Found the theme file?
- if( rFileName == string( pszDirContent ) )
- {
- themeFilePath = newURI;
- free( pszDirContent );
- closedir( pCurrDir );
- return true;
- }
- }
- }
- free( pszDirContent );
- }
- closedir( pCurrDir );
- return false;
- }
- #if !defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
- /* Values used in typeflag field */
- #define REGTYPE '0' /* regular file */
- #define AREGTYPE ' ' /* regular file */
- #define DIRTYPE '5' /* directory */
- #define BLOCKSIZE 512
- struct 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;
- };
- int tar_open( TAR **t, char *pathname, int oflags )
- {
- gzFile f = gzopen( pathname, "rb" );
- if( f == NULL )
- {
- fprintf( stderr, "Couldn't gzopen %sn", 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, "%sn", gzerror(*t, &err) );
- }
- /*
- * Always expect complete blocks to process
- * the tar information.
- */
- if( len != 0 && len != BLOCKSIZE )
- {
- fprintf( stderr, "gzread: incomplete block readn" );
- 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 filen");
- 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 = ' ';
- makedir( fname );
- *p = '/';
- outfile = fopen( fname, "wb" );
- if( !outfile )
- {
- fprintf( stderr, "tar couldn't create %sn",
- 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 );
- outfile = NULL;
- 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 gzclosen" );
- 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;
- }
- #endif
- #ifdef WIN32
- # define mkdir(dirname,mode) _mkdir(dirname)
- #endif
- /* 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( const 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] = ' ';
- }
- 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 %sn", buffer );
- free( buffer );
- return 0;
- }
- if( hold == 0 ) break;
- *p++ = hold;
- }
- free( buffer );
- return 1;
- }
- #ifdef HAVE_ZLIB_H
- static int currentGzFd = -1;
- static void * currentGzVp = NULL;
- int gzopen_frontend( const char *pathname, int oflags, int mode )
- {
- const char *gzflags;
- gzFile gzf;
- switch( oflags )
- {
- 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;
- }
- /** Hum ... */
- currentGzFd = 42;
- currentGzVp = gzf;
- return currentGzFd;
- }
- int gzclose_frontend( int fd )
- {
- if( currentGzVp != NULL && fd != -1 )
- {
- void *toClose = currentGzVp;
- currentGzVp = NULL; currentGzFd = -1;
- return gzclose( toClose );
- }
- return -1;
- }
- int gzread_frontend( int fd, void *p_buffer, size_t i_length )
- {
- if( currentGzVp != NULL && fd != -1 )
- {
- return gzread( currentGzVp, p_buffer, i_length );
- }
- return -1;
- }
- int gzwrite_frontend( int fd, const void * p_buffer, size_t i_length )
- {
- if( currentGzVp != NULL && fd != -1 )
- {
- return gzwrite( currentGzVp, const_cast<void*>(p_buffer), i_length );
- }
- return -1;
- }
- #endif