]> git.sesse.net Git - vlc/blobdiff - modules/access/zip/zipaccess.c
Merge branch 'master' into lpcm_encoder
[vlc] / modules / access / zip / zipaccess.c
index d60f3dcb84a4f6c37c394d47b75551538c3c8926..9f4faf46ed64a0df4830cdb32e8903be3d122a8a 100644 (file)
@@ -22,7 +22,7 @@
  *****************************************************************************/
 
 /** @todo:
- * - implement crypto (using url zip://user:password@path-to-archive#ZIP#file
+ * - implement crypto (using url zip://user:password@path-to-archive!/file)
  * - read files in zip with long name (use unz_file_info.size_filename)
  * - multi-volume archive support ?
  */
@@ -31,8 +31,6 @@
 # include "config.h"
 #endif
 
-#ifdef HAVE_ZLIB_H
-
 #include "zip.h"
 #include <vlc_access.h>
 
@@ -51,8 +49,49 @@ struct access_sys_t
 
 static int AccessControl( access_t *p_access, int i_query, va_list args );
 static ssize_t AccessRead( access_t *, uint8_t *, size_t );
-static int AccessSeek( access_t *, int64_t );
-static int OpenFileInZip( access_t *p_access, int i_pos );
+static int AccessSeek( access_t *, uint64_t );
+static int OpenFileInZip( access_t *p_access, uint64_t i_pos );
+static char *unescapeXml( const char *psz_text );
+
+/** **************************************************************************
+ * \brief Unescape valid XML string
+ * The exact reverse of escapeToXml (zipstream.c)
+ *****************************************************************************/
+static char *unescapeXml( const char *psz_text )
+{
+    char *psz_ret = malloc( strlen( psz_text ) + 1 );
+    if( !psz_ret ) return NULL;
+
+    char *psz_tmp = psz_ret;
+    for( char *psz_iter = (char*) psz_text; *psz_iter; ++psz_iter, ++psz_tmp )
+    {
+        if( *psz_iter == '?' )
+        {
+            int i_value;
+            if( !sscanf( ++psz_iter, "%02x", &i_value ) )
+            {
+                /* Invalid number: URL incorrectly encoded */
+                free( psz_ret );
+                return NULL;
+            }
+            *psz_tmp = (char) i_value;
+            psz_iter++;
+        }
+        else if( isAllowedChar( *psz_iter ) )
+        {
+            *psz_tmp = *psz_iter;
+        }
+        else
+        {
+            /* Invalid character encoding for the URL */
+            free( psz_ret );
+            return NULL;
+        }
+    }
+    *psz_tmp = '\0';
+
+    return psz_ret;
+}
 
 /** **************************************************************************
  * \brief Open access
@@ -66,20 +105,35 @@ int AccessOpen( vlc_object_t *p_this )
 
     char *psz_pathToZip = NULL, *psz_path = NULL, *psz_sep = NULL;
 
+    if( !strstr( p_access->psz_location, ZIP_SEP ) )
+    {
+        msg_Dbg( p_access, "location does not contain separator " ZIP_SEP );
+        return VLC_EGENERIC;
+    }
+
     p_access->p_sys = p_sys = (access_sys_t*)
-            calloc( sizeof( access_sys_t ), 1 );
+            calloc( 1, sizeof( access_sys_t ) );
     if( !p_sys )
         return VLC_ENOMEM;
 
     /* Split the MRL */
-    psz_path = strdup( p_access->psz_path );
-    psz_sep = strchr( psz_path, ZIP_SEP_CHAR );
-    if( !psz_sep )
-        return VLC_EGENERIC;
+    psz_path = strdup( p_access->psz_location );
+    psz_sep = strstr( psz_path, ZIP_SEP );
 
     *psz_sep = '\0';
-    psz_pathToZip = unescape_URI_duplicate( psz_path );
-    p_sys->psz_fileInzip = strdup( psz_sep + 1 );
+    psz_pathToZip = unescapeXml( psz_path );
+    if( !psz_pathToZip )
+    {
+        /* Maybe this was not an encoded string */
+        msg_Dbg( p_access, "not an encoded URL  Trying file '%s'",
+                 psz_path );
+        psz_pathToZip = strdup( psz_path );
+    }
+    p_sys->psz_fileInzip = unescapeXml( psz_sep + ZIP_SEP_LEN );
+    if( !p_sys->psz_fileInzip )
+    {
+        p_sys->psz_fileInzip = strdup( psz_sep + ZIP_SEP_LEN );
+    }
 
     /* Define IO functions */
     zlib_filefunc_def *p_func = (zlib_filefunc_def*)
@@ -111,7 +165,7 @@ int AccessOpen( vlc_object_t *p_this )
     unz_file_info z_info;
     unzGetCurrentFileInfo( file, &z_info, NULL, 0, NULL, 0, NULL, 0 );
 
-    /* Set access informations: size is needed for AccessSeek */
+    /* Set access information: size is needed for AccessSeek */
     p_access->info.i_size = z_info.uncompressed_size;
     p_access->info.i_pos  = 0;
     p_access->info.b_eof  = false;
@@ -233,7 +287,7 @@ static ssize_t AccessRead( access_t *p_access, uint8_t *p_buffer, size_t sz )
 /** **************************************************************************
  * \brief Seek inside zip file
  *****************************************************************************/
-static int AccessSeek( access_t *p_access, int64_t seek_len )
+static int AccessSeek( access_t *p_access, uint64_t seek_len )
 {
     access_sys_t *p_sys = p_access->p_sys;
     assert( p_sys );
@@ -251,7 +305,7 @@ static int AccessSeek( access_t *p_access, int64_t seek_len )
     }
 
     /* Read seek_len data and drop it */
-    int i_seek = 0;
+    unsigned i_seek = 0;
     int i_read = 1;
     char *p_buffer = ( char* ) calloc( 1, ZIP_BUFFER_LEN );
     while( ( i_seek < seek_len ) && ( i_read > 0 ) )
@@ -279,7 +333,7 @@ static int AccessSeek( access_t *p_access, int64_t seek_len )
 /** **************************************************************************
  * \brief Open file in zip
  *****************************************************************************/
-static int OpenFileInZip( access_t *p_access, int i_pos )
+static int OpenFileInZip( access_t *p_access, uint64_t i_pos )
 {
     access_sys_t *p_sys = p_access->p_sys;
     unzFile file = p_sys->zipFile;
@@ -288,7 +342,6 @@ static int OpenFileInZip( access_t *p_access, int i_pos )
         return VLC_EGENERIC;
     }
 
-    i_pos = __MIN( i_pos, 0 );
     p_access->info.i_pos = 0;
 
     unzCloseCurrentFile( file ); /* returns UNZ_PARAMERROR if file not opened */
@@ -381,6 +434,8 @@ static long ZCALLBACK ZipIO_Seek( void* opaque, void* stream,
         default:
             return -1;
     }
+    if( pos < 0 )
+        return -1;
     //msg_Dbg( p_access, "seek (%d,%d): %" PRIu64, offset, origin, pos );
     stream_Seek( (stream_t*) stream, pos );
     /* Note: in unzip.c, unzlocal_SearchCentralDir seeks to the end of
@@ -409,9 +464,3 @@ static int ZCALLBACK ZipIO_Error( void* opaque, void* stream )
     //msg_Dbg( p_access, "error" );
     return 0;
 }
-
-
-
-#else
-# error Can not compile zip demuxer without zlib support
-#endif