>From f6ba176ae8bdef483e46a4b358947bf05b399917 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Filip=20Ros=C3=A9en?= <filip@atch.se>
Date: Fri, 16 Dec 2016 13:41:49 +0100
Subject: [PATCH 5/8] gui/skins2: remove legacy archive dependencies

This is now handled by ThemeLoader::unarchive, and is therefore no
longer needed.
---
 configure.ac                            |   6 +-
 modules/gui/skins2/src/theme_loader.cpp | 626 +++-----------------------------
 modules/gui/skins2/src/theme_loader.hpp |  30 --
 3 files changed, 49 insertions(+), 613 deletions(-)

diff --git a/configure.ac b/configure.ac
index 00285a900a..7627acb4e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -854,19 +854,15 @@ AC_CHECK_HEADERS(zlib.h, [ have_zlib=yes ], [ have_zlib=no ])
 AM_CONDITIONAL(HAVE_ZLIB, [ test "${have_zlib}" = "yes" ])
 if test "${have_zlib}" = "yes"
 then
-  VLC_ADD_LIBS([skins2 sap unzip zip],[-lz])
+  VLC_ADD_LIBS([sap],[-lz])
   PKG_CHECK_MODULES([MINIZIP], [minizip] , [ have_minizip=yes ], [
     AC_CHECK_HEADERS([unzip.h], [
       have_minizip=yes
       MINIZIP_LIBS="-lminizip -lz"
     ], [
-      VLC_ADD_CPPFLAGS([skins2], [-I\\\$(top_srcdir)/modules/access/zip/unzip])
-      VLC_ADD_LIBS([skins2], [\\\$(top_builddir)/modules/libunzip.la])
       have_minizip=no
     ])
   ])
-  VLC_ADD_CPPFLAGS([skins2],[$MINIZIP_CFLAGS])
-  VLC_ADD_LIBS([skins2],[$MINIZIP_LIBS])
 fi
 AM_CONDITIONAL(HAVE_MINIZIP, [ test "${have_minizip}" = "yes" ])
 
diff --git a/modules/gui/skins2/src/theme_loader.cpp b/modules/gui/skins2/src/theme_loader.cpp
index a90047e098..a7aa5138cb 100644
--- a/modules/gui/skins2/src/theme_loader.cpp
+++ b/modules/gui/skins2/src/theme_loader.cpp
@@ -45,253 +45,86 @@
 #include "../src/vlcproc.hpp"
 #include "../src/window_manager.hpp"
 
-#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
-
-#ifndef O_BINARY
-#   define O_BINARY 0
-#endif
 
-bool ThemeLoader::load( const std::string &fileName )
+/* 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
+ */
+static int makedir( const char *newdir )
 {
-    std::string path = getFilePath( fileName );
-
-    //Before all, let's see if the file is present
-    struct stat p_stat;
-    if( vlc_stat( fileName.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( 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;
-
-    // Restore the theme configuration
-    getIntf()->p_sys->p_theme->loadConfig();
-
-    // Retain new loaded skins in config
-    config_PutPsz( getIntf(), "skins2-last", fileName.c_str() );
-
-    return true;
-}
-
+    char *p, *buffer = strdup( newdir );
+    int  len = strlen( buffer );
 
-#if defined( HAVE_ZLIB_H )
-bool ThemeLoader::extractTarGz( const std::string &tarFile, const std::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
+    if( len <= 0 )
     {
-        msg_Dbg( getIntf(), "failed to open %s as a gzip tar file",
-                            tarFile.c_str() );
-        return false;
+        free( buffer );
+        return 0;
     }
 
-    if( tar_extract_all( t, (char *)rootDir.c_str() ) != 0 )
+    if( buffer[len-1] == '/' )
     {
-        tar_close( t );
-        return false;
+        buffer[len-1] = '\0';
     }
 
-    if( tar_close( t ) != 0 )
+    if( vlc_mkdir( buffer, 0775 ) == 0 )
     {
-        return false;
+        free( buffer );
+        return 1;
     }
 
-    return true;
-}
-
-static voidpf ZCALLBACK open_vlc( voidpf opaque, const char *filename, int mode)
-{
-    (void)mode;
-    intf_thread_t *pIntf = (intf_thread_t *)opaque;
-
-    FILE *stream = vlc_fopen( filename, "rb" );
-    if( stream == NULL )
-        msg_Dbg( pIntf, "vlc_fopen failed for %s", filename );
-    return stream;
-}
-
-bool ThemeLoader::extractZip( const std::string &zipFile, const std::string &rootDir )
-{
-    bool b_isWsz = strstr( zipFile.c_str(), ".wsz" );
-
-    // Try to open the ZIP file
-    zlib_filefunc_def descr;
-    fill_fopen_filefunc( &descr );
-    descr.zopen_file = open_vlc;
-    descr.opaque = getIntf();
-
-    unzFile file = unzOpen2( zipFile.c_str(), &descr );
-    if( file == 0 )
-    {
-        msg_Dbg( getIntf(), "failed to open %s as a zip file",
-                 zipFile.c_str() );
-        return false;
-    }
-    unz_global_info info;
-    if( unzGetGlobalInfo( file, &info ) != UNZ_OK )
-    {
-        msg_Dbg( getIntf(), "failed to read zip info from %s",
-                 zipFile.c_str() );
-        unzClose( file );
-        return false;
-    }
-    // Extract all the files in the archive
-    for( unsigned long i = 0; i < info.number_entry; i++ )
+    p = buffer + 1;
+    while( 1 )
     {
-        if( !extractFileInZip( file, rootDir, b_isWsz ) )
-        {
-            msg_Warn( getIntf(), "error while unzipping %s",
-                      zipFile.c_str() );
-            unzClose( file );
-            return false;
-        }
+        char hold;
 
-        if( i < info.number_entry - 1 )
+        while( *p && *p != '\\' && *p != '/' ) p++;
+        hold = *p;
+        *p = 0;
+        if( ( vlc_mkdir( buffer, 0775 ) == -1 ) && ( errno == ENOENT ) )
         {
-            // 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;
-            }
+            fprintf( stderr, "couldn't create directory %s\n", buffer );
+            free( buffer );
+            return 0;
         }
+        if( hold == 0 ) break;
+        *p++ = hold;
     }
-    unzClose( file );
-    return true;
+    free( buffer );
+    return 1;
 }
 
-
-bool ThemeLoader::extractFileInZip( unzFile file, const std::string &rootDir,
-                                    bool isWsz )
+bool ThemeLoader::load( const std::string &fileName )
 {
-    // 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;
-    }
-
-    // Convert the file name to lower case, because some winamp skins
-    // use the wrong case...
-    if( isWsz )
-        for( size_t i = 0; i < strlen( filenameInZip ); i++ )
-            filenameInZip[i] = tolower( (unsigned char)filenameInZip[i] );
+    std::string path = getFilePath( fileName );
 
-    // Allocate the buffer
-    void *pBuffer = malloc( ZIP_BUFFER_SIZE );
-    if( !pBuffer )
+    //Before all, let's see if the file is present
+    struct stat p_stat;
+    if( vlc_stat( fileName.c_str(), &p_stat ) )
         return false;
 
-    // Get the path of the file
-    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
-    std::string fullPath = rootDir
-        + pOsFactory->getDirSeparator()
-        + fixDirSeparators( filenameInZip );
-    std::string basePath = getFilePath( fullPath );
+    // First, we try to un-targz the file, and if it fails we hope it's a XML
+    // file...
 
-    // Extract the file if is not a directory
-    if( basePath != fullPath )
-    {
-        if( unzOpenCurrentFile( file ) )
-        {
-            free( pBuffer );
-            return false;
-        }
-        makedir( basePath.c_str() );
-        FILE *fout = vlc_fopen( fullPath.c_str(), "wb" );
-        if( fout == NULL )
-        {
-            msg_Err( getIntf(), "error opening %s", fullPath.c_str() );
-            free( pBuffer );
-            return false;
-        }
+    if( ! extract( fileName ) && ! parse( path, fileName ) )
+        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" );
-                fclose(fout);
-                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() );
-                    fclose(fout);
-                    free( pBuffer );
-                    return false;
-                }
-            }
-        } while( n > 0 );
+    Theme *pNewTheme = getIntf()->p_sys->p_theme;
+    if( !pNewTheme )
+        return false;
 
-        fclose(fout);
+    // Restore the theme configuration
+    getIntf()->p_sys->p_theme->loadConfig();
 
-        if( unzCloseCurrentFile( file ) != UNZ_OK )
-        {
-            free( pBuffer );
-            return false;
-        }
-    }
+    // Retain new loaded skins in config
+    config_PutPsz( getIntf(), "skins2-last", fileName.c_str() );
 
-    free( pBuffer );
     return true;
 }
 
-
 bool ThemeLoader::extract( const std::string &fileName )
 {
     bool result = true;
@@ -472,8 +305,6 @@ void ThemeLoader::deleteTempFiles( const std::string &path )
 {
     OSFactory::instance( getIntf() )->rmDir( path );
 }
-#endif // HAVE_ZLIB_H
-
 
 bool ThemeLoader::parse( const std::string &path, const std::string &xmlFile )
 {
@@ -514,22 +345,6 @@ std::string ThemeLoader::getFilePath( const std::string &rFullPath )
     return basePath;
 }
 
-
-std::string ThemeLoader::fixDirSeparators( const std::string &rPath )
-{
-    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
-    const std::string &sep = pOsFactory->getDirSeparator();
-    std::string::size_type p = rPath.find( "/", 0 );
-    std::string newPath = rPath;
-    while( p != std::string::npos )
-    {
-        newPath = newPath.replace( p, 1, sep );
-        p = newPath.find( "/", p + 1 );
-    }
-    return newPath;
-}
-
-
 bool ThemeLoader::findFile( const std::string &rootDir, const std::string &rFileName,
                             std::string &themeFilePath )
 {
@@ -592,351 +407,6 @@ bool ThemeLoader::findFile( const std::string &rootDir, const std::string &rFile
     return false;
 }
 
-
-#if !defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
-
-/* Values used in typeflag field */
-#define REGTYPE  '0'            /* regular file */
-#define AREGTYPE '\0'           /* 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 )
-{
-    (void)oflags;
-
-    int fd = vlc_open( pathname, O_BINARY | O_RDONLY );
-    if( fd == -1 )
-    {
-        fprintf( stderr, "Couldn't open %s\n", pathname );
-        return -1;
-    }
-    gzFile f = gzdopen( fd, "rb" );
-    if( f == NULL )
-    {
-        fprintf( stderr, "Couldn't gzopen %s\n", pathname );
-        vlc_close( fd );
-        return -1;
-    }
-
-    *t = (gzFile *)malloc( sizeof(gzFile) );
-    if( *t == NULL )
-    {
-        gzclose( f );
-        return -1;
-    }
-    **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;
-#if defined( _WIN32 )
-    long  path_max = PATH_MAX;
-#else
-    long  path_max = pathconf (".", _PC_PATH_MAX);
-#endif
-    size_t maxsize = (path_max == -1 || path_max > 4096) ? 4096 : path_max;
-    char  fname[BLOCKSIZE + maxsize];
-
-    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;
-            }
-
-            snprintf( fname, sizeof(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 = NULL; else
-                {
-                    outfile = vlc_fopen( fname, "wb" );
-                    if( outfile == NULL )
-                    {
-                        /* try creating directory */
-                        char *p = strrchr( fname, '/' );
-                        if( p != NULL )
-                        {
-                            *p = '\0';
-                            makedir( fname );
-                            *p = '/';
-                            outfile = vlc_fopen( fname, "wb" );
-                            if( !outfile )
-                            {
-                                fprintf( stderr, "tar couldn't create %s\n",
-                                         fname );
-                            }
-                        }
-                    }
-                }
-
-                /*
-                 * 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;
-                    vlc_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;
-}
-
-#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] = '\0';
-    }
-
-    if( vlc_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( ( vlc_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;
-}
-
-#ifdef HAVE_ZLIB_H
-
-static int currentGzFd = -1;
-static void * currentGzVp = NULL;
-
-int gzopen_frontend( const char *pathname, int oflags, int mode )
-{
-    (void)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;
-    }
-    int fd = vlc_open( pathname, oflags );
-    if( fd == -1 )
-    {
-        fprintf( stderr, "Couldn't open %s\n", pathname );
-        return -1;
-    }
-    gzf = gzdopen( fd, gzflags );
-    if( !gzf )
-    {
-        errno = ENOMEM;
-        vlc_close( fd );
-        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( (gzFile) toClose );
-    }
-    return -1;
-}
-
-int gzread_frontend( int fd, void *p_buffer, size_t i_length )
-{
-    if( currentGzVp != NULL && fd != -1 )
-    {
-        return gzread( (gzFile) 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( (gzFile) currentGzVp, const_cast<void*>(p_buffer), i_length );
-    }
-    return -1;
-}
-
 // FIXME: could become a skins2 OS factory function or a vlc core function
 std::string ThemeLoader::getTmpDir( )
 {
@@ -965,4 +435,4 @@ std::string ThemeLoader::getTmpDir( )
 #endif
 }
 
-#endif
+
diff --git a/modules/gui/skins2/src/theme_loader.hpp b/modules/gui/skins2/src/theme_loader.hpp
index e5b35b150f..76f48c1178 100644
--- a/modules/gui/skins2/src/theme_loader.hpp
+++ b/modules/gui/skins2/src/theme_loader.hpp
@@ -27,9 +27,6 @@
 
 #include "skin_common.hpp"
 #include <string>
-#if defined( HAVE_ZLIB_H )
-#   include "unzip.h"
-#endif
 
 class ThemeLoader: public SkinObject
 {
@@ -41,7 +38,6 @@ public:
     bool load( const std::string &fileName );
 
 private:
-#if defined( HAVE_ZLIB_H )
     /// Extract files from an archive (handles tar.gz and zip)
     /**
      * Expects a string from the current locale.
@@ -50,33 +46,10 @@ private:
 
     bool unarchive( const std::string &fileName, const std::string &tempPath );
 
-    /// Extract files from a tar.gz archive
-    /**
-     * Expects strings from the current locale.
-     */
-    bool extractTarGz( const std::string &tarFile, const std::string &rootDir );
-
-    /// Extract files from a .zip archive
-    /**
-     * Expects strings from the current locale.
-     */
-    bool extractZip( const std::string &zipFile, const std::string &rootDir );
-
-    /// Extract the current file from a .zip archive
-    /**
-     * Expects a string from the current locale.
-     */
-    bool extractFileInZip( unzFile file, const std::string &rootDir, bool isWsz );
-
-    /// Clean up the temporary files created by the extraction
-    /**
-     * Expects a string from the current locale.
-     */
     void deleteTempFiles( const std::string &path );
 
     /// Get a unique temporary directory
     std::string getTmpDir( );
-#endif
 
     /// Parse the XML file given as a parameter and build the skin
     /**
@@ -97,9 +70,6 @@ private:
 
     /// Get the base path of a file
     std::string getFilePath( const std::string &rFullPath );
-
-    /// Replace '/' separators by the actual separator of the OS
-    std::string fixDirSeparators( const std::string &rPath );
 };
 
 #endif
-- 
2.11.1

