X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fskins2%2Fsrc%2Ftheme_loader.cpp;h=b48a45338eb6aa3d5faf9f10f9c56156f4e9c5b6;hb=8e20a9cfb1b049db8316e754392d1cfc483f94e4;hp=90fda91ad06a4393c8db5bfd531ddf55cca52f92;hpb=dccb47b82b469f118b6ced550c3cee3bc7ad202c;p=vlc diff --git a/modules/gui/skins2/src/theme_loader.cpp b/modules/gui/skins2/src/theme_loader.cpp index 90fda91ad0..b48a45338e 100644 --- a/modules/gui/skins2/src/theme_loader.cpp +++ b/modules/gui/skins2/src/theme_loader.cpp @@ -61,21 +61,26 @@ 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 ) { // First, we try to un-targz the file, and if it fails we hope it's a XML // file... + string path = getFilePath( fileName ); #if defined( HAVE_ZLIB_H ) - if( ! extract( fileName ) && ! parse( fileName ) ) + if( ! extract( fileName ) && ! parse( path, fileName ) ) return false; #else - if( ! parse( fileName ) ) + if( ! parse( path, fileName ) ) return false; #endif @@ -143,29 +148,177 @@ bool ThemeLoader::extractTarGz( const string &tarFile, const string &rootDir ) } +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() ); + 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() ); + return false; + } + } + } + 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; + } + + // Allocate the buffer + void *pBuffer = malloc( ZIP_BUFFER_SIZE ); + if( !pBuffer ) + { + msg_Err( getIntf(), "Failed to allocate memory" ); + return false; + } + + // Get the path of the file + string fullPath = rootDir + "/" + 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 = tmpdir; free( tmpdir ); // Extract the file in a temporary directory - if( ! extractTarGz( fileName, tempPath ) ) + if( ! extractTarGz( fileName, tempPath ) && + ! extractZip( fileName, tempPath ) ) return false; - // Find the XML file and parse it + string path; string xmlFile; - if( ! findThemeFile( tempPath, xmlFile ) || ! parse( xmlFile ) ) + OSFactory *pOsFactory = OSFactory::instance( getIntf() ); + // Find the XML file in the theme + if( findFile( tempPath, DEFAULT_XML_FILE, xmlFile ) ) { - msg_Err( getIntf(), "%s doesn't contain a " DEFAULT_XML_FILE " file", - fileName.c_str() ); - deleteTempFiles( tempPath ); - return false; + 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(), "Try to load a winamp2 skin" ); + path = getFilePath( mainBmp ); + + // Look for winamp2.xml in the resource path + list resPath = pOsFactory->getResourcePath(); + list::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 true; + return result; } @@ -176,24 +329,11 @@ void ThemeLoader::deleteTempFiles( const string &path ) #endif // HAVE_ZLIB_H -bool ThemeLoader::parse( const string &xmlFile ) +bool ThemeLoader::parse( const string &path, const string &xmlFile ) { // File loaded msg_Dbg( getIntf(), "Using skin file: %s", xmlFile.c_str() ); - // Extract the path of the XML file - string path; - const string &sep = OSFactory::instance( getIntf() )->getDirSeparator(); - string::size_type p = xmlFile.rfind( sep, xmlFile.size() ); - if( p != string::npos ) - { - path = xmlFile.substr( 0, p + 1 ); - } - else - { - path = ""; - } - // Start the parser SkinParser parser( getIntf(), xmlFile, path ); if( ! parser.parse() ) @@ -210,7 +350,30 @@ bool ThemeLoader::parse( const string &xmlFile ) } -bool ThemeLoader::findThemeFile( const string &rootDir, string &themeFilePath ) +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; +} + + +bool ThemeLoader::findFile( const string &rootDir, const string &rFileName, + string &themeFilePath ) { // Path separator const string &sep = OSFactory::instance( getIntf() )->getDirSeparator(); @@ -250,8 +413,8 @@ bool ThemeLoader::findThemeFile( const string &rootDir, string &themeFilePath ) if( 0 ) #endif { - // Can we find the theme file in this subdirectory? - if( findThemeFile( newURI, themeFilePath ) ) + // Can we find the file in this subdirectory? + if( findFile( newURI, rFileName, themeFilePath ) ) { closedir( pCurrDir ); return true; @@ -260,8 +423,7 @@ bool ThemeLoader::findThemeFile( const string &rootDir, string &themeFilePath ) else { // Found the theme file? - if( string( DEFAULT_XML_FILE ) == - string( pDirContent->d_name ) ) + if( rFileName == string( pDirContent->d_name ) ) { themeFilePath = newURI; closedir( pCurrDir ); @@ -280,10 +442,6 @@ bool ThemeLoader::findThemeFile( const string &rootDir, string &themeFilePath ) #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 */ @@ -319,9 +477,6 @@ union tar_buffer { }; -/* helper functions */ -int getoct( char *p, int width ); -int makedir( char *newdir ); int tar_open( TAR **t, char *pathname, int oflags ) { @@ -483,6 +638,11 @@ int getoct( char *p, int width ) 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 @@ -490,7 +650,7 @@ int getoct( char *p, int width ) * * return 1 if OK, 0 on error */ -int makedir( char *newdir ) +int makedir( const char *newdir ) { char *p, *buffer = strdup( newdir ); int len = strlen( buffer ); @@ -532,7 +692,6 @@ int makedir( char *newdir ) free( buffer ); return 1; } -#endif #ifdef HAVE_ZLIB_H