]> git.sesse.net Git - vlc/blobdiff - modules/gui/skins2/src/theme_loader.cpp
Finish the initialization in the Open function.
[vlc] / modules / gui / skins2 / src / theme_loader.cpp
index 1b5dcc3f43aec0d64f6b57c29aeede76c15b2233..c547fda7c72d48f89340e4b843e034f4dc17548f 100644 (file)
@@ -5,7 +5,7 @@
  * $Id$
  *
  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
- *          Olivier Teulière <ipkiss@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
@@ -19,7 +19,7 @@
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #include "theme_loader.hpp"
@@ -30,6 +30,8 @@
 #include "../src/vlcproc.hpp"
 #include "../src/window_manager.hpp"
 
+#include <cctype>
+
 #ifdef HAVE_FCNTL_H
 #   include <fcntl.h>
 #endif
@@ -50,7 +52,7 @@
 #if defined( HAVE_ZLIB_H )
 #   include <zlib.h>
 #   include <errno.h>
-int gzopen_frontend ( char *pathname, int oflags, int mode );
+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 );
@@ -73,11 +75,18 @@ int makedir( const char *newdir );
 
 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...
-    string path = getFilePath( fileName );
+
 #if defined( HAVE_ZLIB_H )
-    if( ! extract( fileName ) && ! parse( path, fileName ) )
+    if( ! extract( sToLocale( fileName ) ) && ! parse( path, fileName ) )
         return false;
 #else
     if( ! parse( path, fileName ) )
@@ -105,7 +114,7 @@ bool ThemeLoader::load( const string &fileName )
         // Show the windows
         pNewTheme->getWindowManager().showAll( true );
     }
-    if( skin_last ) free( skin_last );
+    free( skin_last );
 
     // The new theme cannot embed a video output yet
     VlcProc::instance( getIntf() )->dropVout();
@@ -163,8 +172,9 @@ bool ThemeLoader::extractZip( const string &zipFile, const string &rootDir )
     {
         if( !extractFileInZip( file, rootDir ) )
         {
-            msg_Warn( getIntf(), "Error while unzipping %s",
+            msg_Warn( getIntf(), "error while unzipping %s",
                       zipFile.c_str() );
+            unzClose( file );
             return false;
         }
 
@@ -173,12 +183,14 @@ bool ThemeLoader::extractZip( const string &zipFile, const string &rootDir )
             // Go the next file in the archive
             if( unzGoToNextFile( file ) !=UNZ_OK )
             {
-                msg_Warn( getIntf(), "Error while unzipping %s",
+                msg_Warn( getIntf(), "error while unzipping %s",
                           zipFile.c_str() );
+                unzClose( file );
                 return false;
             }
         }
     }
+    unzClose( file );
     return true;
 }
 
@@ -195,17 +207,23 @@ bool ThemeLoader::extractFileInZip( unzFile file, const string &rootDir )
         return false;
     }
 
+    // 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] );
+    }
+
     // 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
     OSFactory *pOsFactory = OSFactory::instance( getIntf() );
-    string fullPath = rootDir + pOsFactory->getDirSeparator() + filenameInZip;
+    string fullPath = rootDir
+        + pOsFactory->getDirSeparator()
+        + fixDirSeparators( filenameInZip );
     string basePath = getFilePath( fullPath );
 
     // Extract the file if is not a directory
@@ -220,7 +238,7 @@ bool ThemeLoader::extractFileInZip( unzFile file, const string &rootDir )
         FILE *fout = fopen( fullPath.c_str(), "wb" );
         if( fout == NULL )
         {
-            msg_Err( getIntf(), "Error opening %s", fullPath.c_str() );
+            msg_Err( getIntf(), "error opening %s", fullPath.c_str() );
             free( pBuffer );
             return false;
         }
@@ -232,7 +250,7 @@ bool ThemeLoader::extractFileInZip( unzFile file, const string &rootDir )
             n = unzReadCurrentFile( file, pBuffer, ZIP_BUFFER_SIZE );
             if( n < 0 )
             {
-                msg_Err( getIntf(), "Error while reading zip file" );
+                msg_Err( getIntf(), "error while reading zip file" );
                 free( pBuffer );
                 return false;
             }
@@ -240,7 +258,7 @@ bool ThemeLoader::extractFileInZip( unzFile file, const string &rootDir )
             {
                 if( fwrite( pBuffer, n , 1, fout) != 1 )
                 {
-                    msg_Err( getIntf(), "Error while writing %s",
+                    msg_Err( getIntf(), "error while writing %s",
                              fullPath.c_str() );
                     free( pBuffer );
                     return false;
@@ -266,13 +284,16 @@ bool ThemeLoader::extract( const string &fileName )
 {
     bool result = true;
     char *tmpdir = tempnam( NULL, "vlt" );
-    string tempPath = tmpdir;
+    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;
@@ -288,7 +309,7 @@ bool ThemeLoader::extract( const string &fileName )
         string mainBmp;
         if( findFile( tempPath, "main.bmp", mainBmp ) )
         {
-            msg_Dbg( getIntf(), "Try to load a winamp2 skin" );
+            msg_Dbg( getIntf(), "trying to load a winamp2 skin" );
             path = getFilePath( mainBmp );
 
             // Look for winamp2.xml in the resource path
@@ -307,13 +328,13 @@ bool ThemeLoader::extract( const string &fileName )
         // Parse the XML file
         if (! parse( path, xmlFile ) )
         {
-            msg_Err( getIntf(), "Error while parsing %s", xmlFile.c_str() );
+            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() );
+        msg_Err( getIntf(), "no XML found in theme %s", fileName.c_str() );
         result = false;
     }
 
@@ -333,18 +354,18 @@ void ThemeLoader::deleteTempFiles( const string &path )
 bool ThemeLoader::parse( const string &path, const string &xmlFile )
 {
     // File loaded
-    msg_Dbg( getIntf(), "Using skin file: %s", xmlFile.c_str() );
+    msg_Dbg( getIntf(), "using skin file: %s", xmlFile.c_str() );
 
     // Start the parser
     SkinParser parser( getIntf(), xmlFile, path );
     if( ! parser.parse() )
     {
-        msg_Err( getIntf(), "Failed to parse %s", xmlFile.c_str() );
+        msg_Err( getIntf(), "failed to parse %s", xmlFile.c_str() );
         return false;
     }
 
     // Build and store the theme
-    Builder builder( getIntf(), parser.getData() );
+    Builder builder( getIntf(), parser.getData(), path );
     getIntf()->p_sys->p_theme = builder.build();
 
     return true;
@@ -373,6 +394,21 @@ string ThemeLoader::getFilePath( const string &rFullPath )
 }
 
 
+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 )
 {
@@ -380,34 +416,32 @@ bool ThemeLoader::findFile( const string &rootDir, const string &rFileName,
     const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
 
     DIR *pCurrDir;
-    struct dirent *pDirContent;
+    char *pszDirContent;
 
     // Open the dir
-    pCurrDir = opendir( rootDir.c_str() );
+    pCurrDir = utf8_opendir( rootDir.c_str() );
 
     if( pCurrDir == NULL )
     {
         // An error occurred
-        msg_Dbg( getIntf(), "Cannot open directory %s", rootDir.c_str() );
+        msg_Dbg( getIntf(), "cannot open directory %s", rootDir.c_str() );
         return false;
     }
 
-    // Get the first directory entry
-    pDirContent = (dirent*)readdir( pCurrDir );
-
     // While we still have entries in the directory
-    while( pDirContent != NULL )
+    while( ( pszDirContent = utf8_readdir( pCurrDir ) ) != NULL )
     {
-        string newURI = rootDir + sep + pDirContent->d_name;
+        string newURI = rootDir + sep + pszDirContent;
 
         // Skip . and ..
-        if( string( pDirContent->d_name ) != "." &&
-            string( pDirContent->d_name ) != ".." )
+        if( string( pszDirContent ) != "." &&
+            string( pszDirContent ) != ".." )
         {
 #if defined( S_ISDIR )
             struct stat stat_data;
-            stat( newURI.c_str(), &stat_data );
-            if( S_ISDIR(stat_data.st_mode) )
+
+            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
@@ -417,6 +451,7 @@ bool ThemeLoader::findFile( const string &rootDir, const string &rFileName,
                 // Can we find the file in this subdirectory?
                 if( findFile( newURI, rFileName, themeFilePath ) )
                 {
+                    free( pszDirContent );
                     closedir( pCurrDir );
                     return true;
                 }
@@ -424,16 +459,17 @@ bool ThemeLoader::findFile( const string &rootDir, const string &rFileName,
             else
             {
                 // Found the theme file?
-                if( rFileName == string( pDirContent->d_name ) )
+                if( rFileName == string( pszDirContent ) )
                 {
                     themeFilePath = newURI;
+                    free( pszDirContent );
                     closedir( pCurrDir );
                     return true;
                 }
             }
         }
 
-        pDirContent = (dirent*)readdir( pCurrDir );
+        free( pszDirContent );
     }
 
     closedir( pCurrDir );
@@ -593,6 +629,7 @@ int tar_extract_all( TAR *t, char *prefix )
                 {
                     fprintf( stderr, "error writing %s skipping...\n", fname );
                     fclose( outfile );
+                    outfile = NULL;
                     unlink( fname );
                 }
             }
@@ -699,9 +736,9 @@ int makedir( const char *newdir )
 static int currentGzFd = -1;
 static void * currentGzVp = NULL;
 
-int gzopen_frontend( char *pathname, int oflags, int mode )
+int gzopen_frontend( const char *pathname, int oflags, int mode )
 {
-    char *gzflags;
+    const char *gzflags;
     gzFile gzf;
 
     switch( oflags )