diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..2540c67 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.iml +/.idea +/.gradle +.externalNativeBuild +build diff --git a/app/.gitignore b/app/.gitignore new file mode 100755 index 0000000..3543521 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100755 index 0000000..b38effc --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 26 + defaultConfig { + applicationId "io.github.xausky.bh3modmanager" + minSdkVersion 15 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + ndk{ + moduleName "zip" + abiFilters "armeabi-v7a","x86" + } + } + externalNativeBuild { + ndkBuild { + path file("jni/Android.mk") + } + } +} + +dependencies { + implementation 'com.android.support:appcompat-v7:26.1.0' + implementation project(':virtual-app') +} diff --git a/app/jni/Android.mk b/app/jni/Android.mk new file mode 100755 index 0000000..7b987fd --- /dev/null +++ b/app/jni/Android.mk @@ -0,0 +1,28 @@ +# see https://developer.android.com/ndk/guides/android_mk.html + + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libzip + + +LOCAL_CFLAGS := -DHAVE_CONFIG_H=1 +LOCAL_C_INCLUDES += $(LOCAL_PATH)/gladman-fcrypt + + + +MY_PATH=$(LOCAL_PATH) + +# http://falsinsoft.blogspot.de/2014/10/androidmk-include-multiple-source-files.html +LOCAL_SRC_FILES := $(wildcard $(MY_PATH)/*.c) +LOCAL_SRC_FILES := $(LOCAL_SRC_FILES:$(MY_PATH)/%=%) + + + +# link library libz +LOCAL_LDLIBS := -lz -llog + +include $(BUILD_SHARED_LIBRARY) +#include$lude $(BUILD_STATIC_LIBRARY) diff --git a/app/jni/compat.h b/app/jni/compat.h new file mode 100644 index 0000000..f2a5467 --- /dev/null +++ b/app/jni/compat.h @@ -0,0 +1,196 @@ +#ifndef _HAD_LIBZIP_COMPAT_H +#define _HAD_LIBZIP_COMPAT_H + +/* + compat.h -- compatibility defines. + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* to have *_MAX definitions for all types when compiling with g++ */ +#define __STDC_LIMIT_MACROS + +#ifdef _WIN32 +#define ZIP_EXTERN __declspec(dllexport) +/* for dup(), close(), etc. */ +#include +#endif + +#ifdef HAVE_STDBOOL_H +#include +#else +typedef char bool; +#define true 1 +#define false 0 +#endif + +#include + +/* at least MinGW does not provide EOPNOTSUPP, see + * http://sourceforge.net/p/mingw/bugs/263/ + */ +#ifndef EOPNOTSUPP +#define EOPNOTSUPP EINVAL +#endif + +/* at least MinGW does not provide EOVERFLOW, see + * http://sourceforge.net/p/mingw/bugs/242/ + */ +#ifndef EOVERFLOW +#define EOVERFLOW EFBIG +#endif + +#ifdef _WIN32 +#if defined(HAVE__CHMOD) +#define chmod _chmod +#endif +#if defined(HAVE__CLOSE) +#define close _close +#endif +#if defined(HAVE__DUP) +#define dup _dup +#endif +/* crashes reported when using fdopen instead of _fdopen on Windows/Visual Studio 10/Win64 */ +#if defined(HAVE__FDOPEN) +#define fdopen _fdopen +#endif +#if !defined(HAVE_FILENO) && defined(HAVE__FILENO) +#define fileno _fileno +#endif +/* Windows' open() doesn't understand Unix permissions */ +#if defined(HAVE__OPEN) +#define open(a, b, c) _open((a), (b)) +#endif +#if defined(HAVE__SNPRINTF) +#define snprintf _snprintf +#endif +#if defined(HAVE__STRDUP) +#if !defined(HAVE_STRDUP) || defined(_WIN32) +#undef strdup +#define strdup _strdup +#endif +#endif +#if !defined(HAVE__SETMODE) && defined(HAVE_SETMODE) +#define _setmode setmode +#endif +#if !defined(HAVE_STRTOLL) && defined(HAVE__STRTOI64) +#define strtoll _strtoi64 +#endif +#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64) +#define strtoull _strtoui64 +#endif +#if defined(HAVE__UMASK) +#define umask _umask +#endif +#if defined(HAVE__UNLINK) +#define unlink _unlink +#endif +#endif + +#ifndef HAVE_FSEEKO +#define fseeko(s, o, w) (fseek((s), (long int)(o), (w))) +#endif + +#ifndef HAVE_FTELLO +#define ftello(s) ((long)ftell((s))) +#endif + +#ifndef HAVE_MKSTEMP +int _zip_mkstemp(char *); +#define mkstemp _zip_mkstemp +#endif + +#if !defined(HAVE_STRCASECMP) +#if defined(HAVE__STRICMP) +#define strcasecmp _stricmp +#elif defined(HAVE_STRICMP) +#define strcasecmp stricmp +#endif +#endif + +#if SIZEOF_OFF_T == 8 +#define ZIP_OFF_MAX ZIP_INT64_MAX +#define ZIP_OFF_MIN ZIP_INT64_MIN +#elif SIZEOF_OFF_T == 4 +#define ZIP_OFF_MAX ZIP_INT32_MAX +#define ZIP_OFF_MIN ZIP_INT32_MIN +#elif SIZEOF_OFF_T == 2 +#define ZIP_OFF_MAX ZIP_INT16_MAX +#define ZIP_OFF_MIN ZIP_INT16_MIN +#else +#error unsupported size of off_t +#endif + +#if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO) +#define ZIP_FSEEK_MAX ZIP_OFF_MAX +#define ZIP_FSEEK_MIN ZIP_OFF_MIN +#else +#include +#define ZIP_FSEEK_MAX LONG_MAX +#define ZIP_FSEEK_MIN LONG_MIN +#endif + +#ifndef SIZE_MAX +#if SIZEOF_SIZE_T == 8 +#define SIZE_MAX ZIP_INT64_MAX +#elif SIZEOF_SIZE_T == 4 +#define SIZE_MAX ZIP_INT32_MAX +#elif SIZEOF_SIZE_T == 2 +#define SIZE_MAX ZIP_INT16_MAX +#else +#error unsupported size of size_t +#endif +#endif + +#ifndef PRId64 +#ifdef _MSC_VER +#define PRId64 "I64d" +#else +#define PRId64 "lld" +#endif +#endif + +#ifndef PRIu64 +#ifdef _MSC_VER +#define PRIu64 "I64u" +#else +#define PRIu64 "llu" +#endif +#endif + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif + +#endif /* compat.h */ diff --git a/app/jni/config.h b/app/jni/config.h new file mode 100644 index 0000000..1f3a76d --- /dev/null +++ b/app/jni/config.h @@ -0,0 +1,80 @@ +#ifndef HAD_CONFIG_H +#define HAD_CONFIG_H +#ifndef _HAD_ZIPCONF_H +#include "zipconf.h" +#endif +/* BEGIN DEFINES */ +/* #undef HAVE___PROGNAME */ +/* #undef HAVE__CHMOD */ +/* #undef HAVE__CLOSE */ +/* #undef HAVE__DUP */ +/* #undef HAVE__FDOPEN */ +/* #undef HAVE__FILENO */ +/* #undef HAVE__OPEN */ +/* #undef HAVE__SETMODE */ +/* #undef HAVE__SNPRINTF */ +/* #undef HAVE__STRDUP */ +/* #undef HAVE__STRICMP */ +/* #undef HAVE__STRTOI64 */ +/* #undef HAVE__STRTOUI64 */ +/* #undef HAVE__UMASK */ +/* #undef HAVE__UNLINK */ +/* #undef HAVE_CLONEFILE */ +#define HAVE_FILENO +#define HAVE_FSEEKO +#define HAVE_FTELLO +/* #undef HAVE_GETPROGNAME */ +/* #undef HAVE_LIBBZ2 */ +#define HAVE_OPEN +#define HAVE_MKSTEMP +/* #undef HAVE_SETMODE */ +#define HAVE_SNPRINTF +#define HAVE_SSIZE_T_LIBZIP +#define HAVE_STRCASECMP +#define HAVE_STRDUP +/* #undef HAVE_STRICMP */ +#define HAVE_STRTOLL +#define HAVE_STRTOULL +/* #undef HAVE_STRUCT_TM_TM_ZONE */ +#define HAVE_STDBOOL_H +#define HAVE_STRINGS_H +#define HAVE_UNISTD_H +/* #undef __INT8_LIBZIP */ +#define INT8_T_LIBZIP 1 +#define UINT8_T_LIBZIP 1 +/* #undef __INT16_LIBZIP */ +#define INT16_T_LIBZIP 2 +#define UINT16_T_LIBZIP 2 +/* #undef __INT32_LIBZIP */ +#define INT32_T_LIBZIP 4 +#define UINT32_T_LIBZIP 4 +/* #undef __INT64_LIBZIP */ +#define INT64_T_LIBZIP 8 +#define UINT64_T_LIBZIP 8 +#define SIZEOF_OFF_T 8 +#define SIZE_T_LIBZIP 8 +#define SSIZE_T_LIBZIP 8 +/* #undef HAVE_DIRENT_H */ +#define HAVE_FTS_H +/* #undef HAVE_NDIR_H */ +/* #undef HAVE_SYS_DIR_H */ +/* #undef HAVE_SYS_NDIR_H */ +/* #undef WORDS_BIGENDIAN */ +#define HAVE_SHARED +/* END DEFINES */ +#define PACKAGE "libzip" +#define VERSION "1.4.0" + +#ifndef HAVE_SSIZE_T_LIBZIP +# if SIZE_T_LIBZIP == INT_LIBZIP +typedef int ssize_t; +# elif SIZE_T_LIBZIP == LONG_LIBZIP +typedef long ssize_t; +# elif SIZE_T_LIBZIP == LONG_LONG_LIBZIP +typedef long long ssize_t; +# else +#error no suitable type for ssize_t found +# endif +#endif + +#endif /* HAD_CONFIG_H */ diff --git a/app/jni/gladman-fcrypt.c b/app/jni/gladman-fcrypt.c new file mode 100644 index 0000000..44622d3 --- /dev/null +++ b/app/jni/gladman-fcrypt.c @@ -0,0 +1,44 @@ +/* + gladman-fcrypt.c -- wrapper functions for Dr Gladman's AES functions + Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define BUILDING_FCRYPT + +#include "gladman-fcrypt.h" + +#include "gladman-fcrypt/aescrypt.c" +#include "gladman-fcrypt/aeskey.c" +#include "gladman-fcrypt/aestab.c" +#include "gladman-fcrypt/fileenc.c" +#include "gladman-fcrypt/hmac.c" +#include "gladman-fcrypt/pwd2key.c" +#include "gladman-fcrypt/sha1.c" diff --git a/app/jni/gladman-fcrypt.h b/app/jni/gladman-fcrypt.h new file mode 100644 index 0000000..fc61b67 --- /dev/null +++ b/app/jni/gladman-fcrypt.h @@ -0,0 +1,49 @@ +/* + gladman-fcrypt.h -- wrapper functions for Dr Gladman's AES functions + Copyright (C) 2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_GLADMAN_FCRYPT_H +#define HAD_GLADMAN_FCRYPT_H + +/* implementation fetched from + * http://173.254.28.24/~brgladma//oldsite/cryptography_technology/fileencrypt/files.zip + * + * Files dated 01-27-2004 except main.c dated 11-18-2008. + */ + +#include "zipint.h" + +#define INTERNAL static + +#include "fileenc.h" + +#endif /* HAD_GLADMAN_FCRYPT_H */ diff --git a/app/jni/gladman-fcrypt/aes.h b/app/jni/gladman-fcrypt/aes.h new file mode 100644 index 0000000..d8a5f93 --- /dev/null +++ b/app/jni/gladman-fcrypt/aes.h @@ -0,0 +1,128 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file contains the definitions required to use AES and Rijndael in C. +*/ + +#ifndef _AES_H +#define _AES_H + +#if defined(__cplusplus) +extern "C" +{ +#if 0 +} +#endif +#endif + +/* If a table pointer is needed in the AES context, include the define */ +/* #define AES_TABLE_PTR */ + +#include "config.h" + +typedef zip_uint8_t aes_08t; +typedef zip_uint32_t aes_32t; + +/* This BLOCK_SIZE is in BYTES. It can have the values 16, 24, 32 or */ +/* undefined for use with aescrypt.c and aeskey.c, or 16, 20, 24, 28, */ +/* 32 or undefined for use with aescrypp.c and aeskeypp.c. When the */ +/* BLOCK_SIZE is left undefined a version that provides a dynamically */ +/* variable block size is produced but this is MUCH slower. */ + +#define BLOCK_SIZE 16 + +/* key schedule length (in 32-bit words) */ + +#if !defined(BLOCK_SIZE) +#define KS_LENGTH 128 +#else +#define KS_LENGTH (4 * BLOCK_SIZE) +#endif + +typedef unsigned int aes_fret; /* type for function return value */ +#define aes_bad 0 /* bad function return value */ +#define aes_good 1 /* good function return value */ +#ifndef AES_DLL /* implement normal or DLL functions */ +#define aes_rval aes_fret +#else +#define aes_rval aes_fret __declspec(dllexport) _stdcall +#endif + +typedef struct /* the AES context for encryption */ +{ aes_32t k_sch[KS_LENGTH]; /* the encryption key schedule */ + aes_32t n_rnd; /* the number of cipher rounds */ + aes_32t n_blk; /* the number of bytes in the state */ +#if defined(AES_TABLE_PTR) /* where global variables are not */ + void *t_ptr; /* available this pointer is used */ +#endif /* to point to the fixed tables */ +} aes_ctx; + +/* The block length (blen) is input in bytes when it is in the range */ +/* 16 <= blen <= 32 or in bits when in the range 128 <= blen <= 256 */ +/* Only 16 bytes (128 bits) is legal for AES but the files aescrypt.c */ +/* and aeskey.c provide support for 16, 24 and 32 byte (128, 192 and */ +/* 256 bit) blocks while aescrypp.c and aeskeypp.c provide support for */ +/* 16, 20, 24, 28 and 32 byte (128, 160, 192, 224 and 256 bit) blocks. */ +/* The value aes_good is returned if the requested block size is legal, */ +/* otherwise aes_bad is returned. */ + +#if !defined(BLOCK_SIZE) +INTERNAL aes_rval aes_set_block_size(unsigned int blen, aes_ctx cx[1]); +#endif + +/* The key length (klen) is input in bytes when it is in the range */ +/* 16 <= klen <= 32 or in bits when in the range 128 <= klen <= 256 */ +/* The files aescrypt.c and aeskey.c provide support for 16, 24 and */ +/* 32 byte (128, 192 and 256 bit) keys while aescrypp.c and aeskeypp.c */ +/* provide support for 16, 20, 24, 28 and 32 byte (128, 160, 192, 224 */ +/* and 256 bit) keys. The value aes_good is returned if the requested */ +/* key size is legal, otherwise aes_bad is returned. */ + +#ifdef BUILDING_FCRYPT +INTERNAL aes_rval aes_set_encrypt_key(const unsigned char in_key[], + unsigned int klen, aes_ctx cx[1]); +INTERNAL aes_rval aes_encrypt_block(const unsigned char in_blk[], + unsigned char out_blk[], const aes_ctx cx[1]); +#endif + +#if 0 /* not used */ +INTERNAL aes_rval aes_set_decrypt_key(const unsigned char in_key[], + unsigned int klen, aes_ctx cx[1]); +INTERNAL aes_rval aes_decrypt_block(const unsigned char in_blk[], + unsigned char out_blk[], const aes_ctx cx[1]); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/app/jni/gladman-fcrypt/aescrypt.c b/app/jni/gladman-fcrypt/aescrypt.c new file mode 100644 index 0000000..923d617 --- /dev/null +++ b/app/jni/gladman-fcrypt/aescrypt.c @@ -0,0 +1,450 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file contains the code for implementing encryption and decryption + for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It + can optionally be replaced by code written in assembler using NASM. +*/ + +#include "aesopt.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7) +#error An illegal block size has been specified. +#endif + +#define libzip_fcrypt_unused 77 /* Sunset Strip */ + +#define si(y,x,k,c) (s(y,c) = word_in(x + 4 * c) ^ k[c]) +#define so(y,x,c) word_out(y + 4 * c, s(x,c)) + +#if BLOCK_SIZE == 16 + +#if defined(ARRAYS) +#define locals(y,x) x[4],y[4] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 + /* + the following defines prevent the compiler requiring the declaration + of generated but unused variables in the fwd_var and inv_var macros + */ +#define b04 libzip_fcrypt_unused +#define b05 libzip_fcrypt_unused +#define b06 libzip_fcrypt_unused +#define b07 libzip_fcrypt_unused +#define b14 libzip_fcrypt_unused +#define b15 libzip_fcrypt_unused +#define b16 libzip_fcrypt_unused +#define b17 libzip_fcrypt_unused +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) + +#elif BLOCK_SIZE == 24 + +#if defined(ARRAYS) +#define locals(y,x) x[6],y[6] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ + y##0,y##1,y##2,y##3,y##4,y##5 +#define b06 libzip_fcrypt_unused +#define b07 libzip_fcrypt_unused +#define b16 libzip_fcrypt_unused +#define b17 libzip_fcrypt_unused +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); \ + s(y,4) = s(x,4); s(y,5) = s(x,5); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ + si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ + so(y,x,3); so(y,x,4); so(y,x,5) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ + rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) +#else + +#if defined(ARRAYS) +#define locals(y,x) x[8],y[8] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ + y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 +#endif +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); \ + s(y,4) = s(x,4); s(y,5) = s(x,5); \ + s(y,6) = s(x,6); s(y,7) = s(x,7); + +#if BLOCK_SIZE == 32 + +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ + si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ + so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ + rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) +#else + +#define state_in(y,x,k) \ +switch(nc) \ +{ case 8: si(y,x,k,7); si(y,x,k,6); \ + case 6: si(y,x,k,5); si(y,x,k,4); \ + case 4: si(y,x,k,3); si(y,x,k,2); \ + si(y,x,k,1); si(y,x,k,0); \ +} + +#define state_out(y,x) \ +switch(nc) \ +{ case 8: so(y,x,7); so(y,x,6); \ + case 6: so(y,x,5); so(y,x,4); \ + case 4: so(y,x,3); so(y,x,2); \ + so(y,x,1); so(y,x,0); \ +} + +#if defined(FAST_VARIABLE) + +#define round(rm,y,x,k) \ +switch(nc) \ +{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ + rm(y,x,k,5); rm(y,x,k,4); \ + rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ + case 6: rm(y,x,k,5); rm(y,x,k,4); \ + rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ + case 4: rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ + break; \ +} +#else + +#define round(rm,y,x,k) \ +switch(nc) \ +{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ + case 6: rm(y,x,k,5); rm(y,x,k,4); \ + case 4: rm(y,x,k,3); rm(y,x,k,2); \ + rm(y,x,k,1); rm(y,x,k,0); \ +} + +#endif + +#endif +#endif + +#if defined(ENCRYPTION) && !defined(AES_ASM) + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#if defined(BLOCK_SIZE) +#if BLOCK_SIZE == 16 +# define fwd_var(x,r,c) s(x,((r+c)%nc)) +#else +#define fwd_var(x,r,c) s(x,(r+c+(((r>1)&&(nc>9-r))?1:0))%nc) +#endif +#else +#define fwd_var(x,r,c)\ + ( r == 0 ? s(x,c) \ + : r == 1 ? \ + ( c == 0 ? s(x,1) \ + : c == 1 ? s(x,2) \ + : c == 2 ? s(x,3) \ + : c == 3 ? nc == 4 ? s(x,0) : s(x,4) \ + : c == 4 ? s(x,5) \ + : c == 5 ? nc == 8 ? s(x,6) : s(x,0) \ + : c == 6 ? s(x,7) : s(x,0)) \ + : r == 2 ? \ + ( c == 0 ? nc == 8 ? s(x,3) : s(x,2) \ + : c == 1 ? nc == 8 ? s(x,4) : s(x,3) \ + : c == 2 ? nc == 4 ? s(x,0) : nc == 8 ? s(x,5) : s(x,4) \ + : c == 3 ? nc == 4 ? s(x,1) : nc == 8 ? s(x,6) : s(x,5) \ + : c == 4 ? nc == 8 ? s(x,7) : s(x,0) \ + : c == 5 ? nc == 8 ? s(x,0) : s(x,1) \ + : c == 6 ? s(x,1) : s(x,2)) \ + : \ + ( c == 0 ? nc == 8 ? s(x,4) : s(x,3) \ + : c == 1 ? nc == 4 ? s(x,0) : nc == 8 ? s(x,5) : s(x,4) \ + : c == 2 ? nc == 4 ? s(x,1) : nc == 8 ? s(x,6) : s(x,5) \ + : c == 3 ? nc == 4 ? s(x,2) : nc == 8 ? s(x,7) : s(x,0) \ + : c == 4 ? nc == 8 ? s(x,0) : s(x,1) \ + : c == 5 ? nc == 8 ? s(x,1) : s(x,2) \ + : c == 6 ? s(x,2) : s(x,3))) +#endif + +#if defined(FT4_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) +#elif defined(FT1_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) +#else +#define fwd_rnd(y,x,k,c) (s(y,c) = fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)) ^ (k)[c]) +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) +#elif defined(FL1_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) +#else +#define fwd_lrnd(y,x,k,c) (s(y,c) = no_table(x,t_use(s,box),fwd_var,rf1,c) ^ (k)[c]) +#endif + +INTERNAL aes_rval aes_encrypt_block(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ aes_32t locals(b0, b1); + const aes_32t *kp = cx->k_sch; + dec_fmvars /* declare variables for fwd_mcol() if needed */ + + if(!(cx->n_blk & 1)) return aes_bad; + + state_in(b0, in_blk, kp); + +#if (ENC_UNROLL == FULL) + + kp += (cx->n_rnd - 9) * nc; + + /*lint -e{616} control flows into case/default */ + switch(cx->n_rnd) + { + case 14: + round(fwd_rnd, b1, b0, kp - 4 * nc); + round(fwd_rnd, b0, b1, kp - 3 * nc); + /* fallthrough */ + case 12: + round(fwd_rnd, b1, b0, kp - 2 * nc); + round(fwd_rnd, b0, b1, kp - nc); + /* fallthrough */ + case 10: + round(fwd_rnd, b1, b0, kp ); + round(fwd_rnd, b0, b1, kp + nc); + round(fwd_rnd, b1, b0, kp + 2 * nc); + round(fwd_rnd, b0, b1, kp + 3 * nc); + round(fwd_rnd, b1, b0, kp + 4 * nc); + round(fwd_rnd, b0, b1, kp + 5 * nc); + round(fwd_rnd, b1, b0, kp + 6 * nc); + round(fwd_rnd, b0, b1, kp + 7 * nc); + round(fwd_rnd, b1, b0, kp + 8 * nc); + round(fwd_lrnd, b0, b1, kp + 9 * nc); + /* fallthrough */ + default: + ; + } +#else + +#if (ENC_UNROLL == PARTIAL) + { aes_32t rnd; + for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd) + { + kp += nc; + round(fwd_rnd, b1, b0, kp); + kp += nc; + round(fwd_rnd, b0, b1, kp); + } + kp += nc; + round(fwd_rnd, b1, b0, kp); +#else + { aes_32t rnd, *p0 = b0, *p1 = b1, *pt; + for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) + { + kp += nc; + round(fwd_rnd, p1, p0, kp); + pt = p0, p0 = p1, p1 = pt; + } +#endif + kp += nc; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif + +#if defined(DECRYPTION) && !defined(AES_ASM) + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#if defined(BLOCK_SIZE) +#if BLOCK_SIZE == 16 +#define inv_var(x,r,c) s(x,((4+c-r)%nc)) +#else +#define inv_var(x,r,c) s(x,(840+c-r-(((r>1)&&(nc>9-r))?1:0))%nc) +#endif +#else +#define inv_var(x,r,c)\ + ( r == 0 ? s(x,c) \ + : r == 1 ? \ + ( c == 0 ? nc == 4 ? s(x,3) : nc == 8 ? s(x,7) : s(x,5) \ + : c == 1 ? s(x,0) \ + : c == 2 ? s(x,1) \ + : c == 3 ? s(x,2) \ + : c == 4 ? s(x,3) \ + : c == 5 ? s(x,4) \ + : c == 6 ? s(x,5) : s(x,6)) \ + : r == 2 ? \ + ( c == 0 ? nc == 4 ? s(x,2) : nc == 8 ? s(x,5) : s(x,4) \ + : c == 1 ? nc == 4 ? s(x,3) : nc == 8 ? s(x,6) : s(x,5) \ + : c == 2 ? nc == 8 ? s(x,7) : s(x,0) \ + : c == 3 ? nc == 8 ? s(x,0) : s(x,1) \ + : c == 4 ? nc == 8 ? s(x,1) : s(x,2) \ + : c == 5 ? nc == 8 ? s(x,2) : s(x,3) \ + : c == 6 ? s(x,3) : s(x,4)) \ + : \ + ( c == 0 ? nc == 4 ? s(x,1) : nc == 8 ? s(x,4) : s(x,3) \ + : c == 1 ? nc == 4 ? s(x,2) : nc == 8 ? s(x,5) : s(x,4) \ + : c == 2 ? nc == 4 ? s(x,3) : nc == 8 ? s(x,6) : s(x,5) \ + : c == 3 ? nc == 8 ? s(x,7) : s(x,0) \ + : c == 4 ? nc == 8 ? s(x,0) : s(x,1) \ + : c == 5 ? nc == 8 ? s(x,1) : s(x,2) \ + : c == 6 ? s(x,2) : s(x,3))) +#endif + +#if defined(IT4_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) +#elif defined(IT1_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) +#else +#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol(no_table(x,t_use(i,box),inv_var,rf1,c) ^ (k)[c])) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) +#elif defined(IL1_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) +#else +#define inv_lrnd(y,x,k,c) (s(y,c) = no_table(x,t_use(i,box),inv_var,rf1,c) ^ (k)[c]) +#endif + +INTERNAL aes_rval aes_decrypt_block(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ aes_32t locals(b0, b1); + const aes_32t *kp = cx->k_sch + nc * cx->n_rnd; + dec_imvars /* declare variables for inv_mcol() if needed */ + + if(!(cx->n_blk & 2)) return aes_bad; + + state_in(b0, in_blk, kp); + +#if (DEC_UNROLL == FULL) + + kp = cx->k_sch + 9 * nc; + + /*lint -e{616} control flows into case/default */ + switch(cx->n_rnd) + { + case 14: + round(inv_rnd, b1, b0, kp + 4 * nc); + round(inv_rnd, b0, b1, kp + 3 * nc); + case 12: + round(inv_rnd, b1, b0, kp + 2 * nc); + round(inv_rnd, b0, b1, kp + nc ); + case 10: + round(inv_rnd, b1, b0, kp ); + round(inv_rnd, b0, b1, kp - nc); + round(inv_rnd, b1, b0, kp - 2 * nc); + round(inv_rnd, b0, b1, kp - 3 * nc); + round(inv_rnd, b1, b0, kp - 4 * nc); + round(inv_rnd, b0, b1, kp - 5 * nc); + round(inv_rnd, b1, b0, kp - 6 * nc); + round(inv_rnd, b0, b1, kp - 7 * nc); + round(inv_rnd, b1, b0, kp - 8 * nc); + round(inv_lrnd, b0, b1, kp - 9 * nc); + default: + ; + } +#else + +#if (DEC_UNROLL == PARTIAL) + { aes_32t rnd; + for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd) + { + kp -= nc; + round(inv_rnd, b1, b0, kp); + kp -= nc; + round(inv_rnd, b0, b1, kp); + } + kp -= nc; + round(inv_rnd, b1, b0, kp); +#else + { aes_32t rnd, *p0 = b0, *p1 = b1, *pt; + for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) + { + kp -= nc; + round(inv_rnd, p1, p0, kp); + pt = p0, p0 = p1, p1 = pt; + } +#endif + kp -= nc; + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/app/jni/gladman-fcrypt/aeskey.c b/app/jni/gladman-fcrypt/aeskey.c new file mode 100644 index 0000000..e03b48f --- /dev/null +++ b/app/jni/gladman-fcrypt/aeskey.c @@ -0,0 +1,416 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file contains the code for implementing the key schedule for AES and + Rijndael for block and key sizes of 16, 24, and 32 bytes. +*/ + +#include "aesopt.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7) +#error An illegal block size has been specified. +#endif + +/* Subroutine to set the block size (if variable). The value can be + in bytes, with legal values of 16, 24 and 32, or in bits, with + legal values of 128, 192 and 256. +*/ + +#if !defined(BLOCK_SIZE) + +INTERNAL aes_rval aes_set_block_size(unsigned int blen, aes_ctx cx[1]) +{ +#if !defined(FIXED_TABLES) +#ifdef GLOBALS + if(!t_use(in,it)) gen_tabs(); +#else + if(!cx->t_ptr || !t_use(in,it)) gen_tabs(cx); +#endif +#endif + if(((blen & 7) || blen < 16 || blen > 32) && ((blen & 63) || blen < 128 || blen > 256)) + { + cx->n_blk = 0; return aes_bad; + } + else + { + cx->n_blk = blen >> (blen < 128 ? 0 : 3); return aes_good; + } +} + +#endif + +/* Initialise the key schedule from the user supplied key. The key + length can be specified in bytes, with legal values of 16, 24 + and 32, or in bits, with legal values of 128, 192 and 256. These + values correspond with Nk values of 4, 6 and 8 respectively. + + The following macros implement a single cycle in the key + schedule generation process. The number of cycles needed + for each cx->n_col and nk value is: + + nk = 4 5 6 7 8 + ------------------------------ + cx->n_col = 4 10 9 8 7 7 + cx->n_col = 5 14 11 10 9 9 + cx->n_col = 6 19 15 12 11 11 + cx->n_col = 7 21 19 16 13 14 + cx->n_col = 8 29 23 19 17 14 +*/ + +#define ke4(k,i) \ +{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ +} +#define kel4(k,i) \ +{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ +} + +#define ke6(k,i) \ +{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \ + k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \ +} +#define kel6(k,i) \ +{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \ +} + +#define ke8(k,i) \ +{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \ + k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \ + k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \ +} +#define kel8(k,i) \ +{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \ +} + +#if defined(ENCRYPTION_KEY_SCHEDULE) + +INTERNAL aes_rval aes_set_encrypt_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ aes_32t ss[8]; + +#if !defined(FIXED_TABLES) +#ifdef GLOBALS + if(!t_use(in,it)) gen_tabs(); +#else + if(!cx->t_ptr || !t_use(in,it)) gen_tabs(cx); +#endif +#endif + +#if !defined(BLOCK_SIZE) + if(!cx->n_blk) cx->n_blk = 16; +#else + cx->n_blk = BLOCK_SIZE; +#endif + + if(((klen & 7) || klen < 16 || klen > 32) && ((klen & 63) || klen < 128 || klen > 256)) + { + cx->n_rnd = 0; return aes_bad; + } + + klen >>= (klen < 128 ? 2 : 5); + cx->n_blk = (cx->n_blk & ~3U) | 1; + + cx->k_sch[0] = ss[0] = word_in(in_key ); + cx->k_sch[1] = ss[1] = word_in(in_key + 4); + cx->k_sch[2] = ss[2] = word_in(in_key + 8); + cx->k_sch[3] = ss[3] = word_in(in_key + 12); + +#if (BLOCK_SIZE == 16) && (ENC_UNROLL != NONE) + + switch(klen) + { + case 4: + ke4(cx->k_sch, 0); ke4(cx->k_sch, 1); + ke4(cx->k_sch, 2); ke4(cx->k_sch, 3); + ke4(cx->k_sch, 4); ke4(cx->k_sch, 5); + ke4(cx->k_sch, 6); ke4(cx->k_sch, 7); + ke4(cx->k_sch, 8); kel4(cx->k_sch, 9); + cx->n_rnd = 10; break; + case 6: + cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + ke6(cx->k_sch, 0); ke6(cx->k_sch, 1); + ke6(cx->k_sch, 2); ke6(cx->k_sch, 3); + ke6(cx->k_sch, 4); ke6(cx->k_sch, 5); + ke6(cx->k_sch, 6); kel6(cx->k_sch, 7); + cx->n_rnd = 12; break; + case 8: + cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + ke8(cx->k_sch, 0); ke8(cx->k_sch, 1); + ke8(cx->k_sch, 2); ke8(cx->k_sch, 3); + ke8(cx->k_sch, 4); ke8(cx->k_sch, 5); + kel8(cx->k_sch, 6); + cx->n_rnd = 14; break; + default: + ; + } +#else + cx->n_rnd = (klen > nc ? klen : nc) + 6; + { aes_32t i, l; + l = (nc * cx->n_rnd + nc - 1) / klen; + + switch(klen) + { + case 4: + for(i = 0; i < l; ++i) + ke4(cx->k_sch, i); + break; + case 6: + cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + for(i = 0; i < l; ++i) + ke6(cx->k_sch, i); + break; + case 8: + cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + for(i = 0; i < l; ++i) + ke8(cx->k_sch, i); + break; + default: + ; + } + } +#endif + + return aes_good; +} + +#endif + +#if defined(DECRYPTION_KEY_SCHEDULE) + +#if (DEC_ROUND != NO_TABLES) +#define d_vars dec_imvars +#define ff(x) inv_mcol(x) +#else +#define ff(x) (x) +#define d_vars +#endif + +#if 1 +#define kdf4(k,i) \ +{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ + ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \ + ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \ +} +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ + k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \ + k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \ +} +#define kdl4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ + k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \ + k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \ +} +#else +#define kdf4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \ +} +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \ + ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \ + ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \ + ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \ +} +#define kdl4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \ + ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \ +} +#endif + +#define kdf6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \ + ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \ +} +#define kd6(k,i) \ +{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \ + ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \ + ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \ + ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \ + ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \ + ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \ +} +#define kdl6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \ + ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \ +} + +#define kdf8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \ + ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \ + ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \ +} +#define kd8(k,i) \ +{ aes_32t g = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \ + ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \ + ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \ + ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \ + g = ls_box(ss[3],0); \ + ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \ + ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \ + ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \ + ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \ +} +#define kdl8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \ + ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \ +} + +INTERNAL aes_rval aes_set_decrypt_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ aes_32t ss[8]; + d_vars + +#if !defined(FIXED_TABLES) +#ifdef GLOBALS + if(!t_use(in,it)) gen_tabs(); +#else + if(!cx->t_ptr || !t_use(in,it)) gen_tabs(cx); +#endif +#endif + +#if !defined(BLOCK_SIZE) + if(!cx->n_blk) cx->n_blk = 16; +#else + cx->n_blk = BLOCK_SIZE; +#endif + + if(((klen & 7) || klen < 16 || klen > 32) && ((klen & 63) || klen < 128 || klen > 256)) + { + cx->n_rnd = 0; return aes_bad; + } + + klen >>= (klen < 128 ? 2 : 5); + cx->n_blk = (cx->n_blk & ~3) | 2; + + cx->k_sch[0] = ss[0] = word_in(in_key ); + cx->k_sch[1] = ss[1] = word_in(in_key + 4); + cx->k_sch[2] = ss[2] = word_in(in_key + 8); + cx->k_sch[3] = ss[3] = word_in(in_key + 12); + +#if (BLOCK_SIZE == 16) && (DEC_UNROLL != NONE) + + switch(klen) + { + case 4: + kdf4(cx->k_sch, 0); kd4(cx->k_sch, 1); + kd4(cx->k_sch, 2); kd4(cx->k_sch, 3); + kd4(cx->k_sch, 4); kd4(cx->k_sch, 5); + kd4(cx->k_sch, 6); kd4(cx->k_sch, 7); + kd4(cx->k_sch, 8); kdl4(cx->k_sch, 9); + cx->n_rnd = 10; break; + case 6: + cx->k_sch[4] = ff(ss[4] = word_in(in_key + 16)); + cx->k_sch[5] = ff(ss[5] = word_in(in_key + 20)); + kdf6(cx->k_sch, 0); kd6(cx->k_sch, 1); + kd6(cx->k_sch, 2); kd6(cx->k_sch, 3); + kd6(cx->k_sch, 4); kd6(cx->k_sch, 5); + kd6(cx->k_sch, 6); kdl6(cx->k_sch, 7); + cx->n_rnd = 12; break; + case 8: + cx->k_sch[4] = ff(ss[4] = word_in(in_key + 16)); + cx->k_sch[5] = ff(ss[5] = word_in(in_key + 20)); + cx->k_sch[6] = ff(ss[6] = word_in(in_key + 24)); + cx->k_sch[7] = ff(ss[7] = word_in(in_key + 28)); + kdf8(cx->k_sch, 0); kd8(cx->k_sch, 1); + kd8(cx->k_sch, 2); kd8(cx->k_sch, 3); + kd8(cx->k_sch, 4); kd8(cx->k_sch, 5); + kdl8(cx->k_sch, 6); + cx->n_rnd = 14; break; + default: + ; + } +#else + cx->n_rnd = (klen > nc ? klen : nc) + 6; + { aes_32t i, l; + l = (nc * cx->n_rnd + nc - 1) / klen; + + switch(klen) + { + case 4: + for(i = 0; i < l; ++i) + ke4(cx->k_sch, i); + break; + case 6: + cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + for(i = 0; i < l; ++i) + ke6(cx->k_sch, i); + break; + case 8: + cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + for(i = 0; i < l; ++i) + ke8(cx->k_sch, i); + break; + default: + ; + } +#if (DEC_ROUND != NO_TABLES) + for(i = nc; i < nc * cx->n_rnd; ++i) + cx->k_sch[i] = inv_mcol(cx->k_sch[i]); +#endif + } +#endif + + return aes_good; +} + +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/app/jni/gladman-fcrypt/aesopt.h b/app/jni/gladman-fcrypt/aesopt.h new file mode 100644 index 0000000..12db549 --- /dev/null +++ b/app/jni/gladman-fcrypt/aesopt.h @@ -0,0 +1,900 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file contains the compilation options for AES (Rijndael) and code + that is common across encryption, key scheduling and table generation. + + OPERATION + + These source code files implement the AES algorithm Rijndael designed by + Joan Daemen and Vincent Rijmen. The version in aes.c is designed for + block and key sizes of 128, 192 and 256 bits (16, 24 and 32 bytes) while + that in aespp.c provides for block and keys sizes of 128, 160, 192, 224 + and 256 bits (16, 20, 24, 28 and 32 bytes). This file is a common header + file for these two implementations and for aesref.c, which is a reference + implementation. + + This version is designed for flexibility and speed using operations on + 32-bit words rather than operations on bytes. It provides aes_both fixed + and dynamic block and key lengths and can also run with either big or + little endian internal byte order (see aes.h). It inputs block and key + lengths in bytes with the legal values being 16, 24 and 32 for aes.c and + 16, 20, 24, 28 and 32 for aespp.c + + THE CIPHER INTERFACE + + aes_08t (an unsigned 8-bit type) + aes_32t (an unsigned 32-bit type) + aes_fret (a signed 16 bit type for function return values) + aes_good (value != 0, a good return) + aes_bad (value == 0, an error return) + struct aes_ctx (structure for the cipher encryption context) + struct aes_ctx (structure for the cipher decryption context) + aes_rval the function return type (aes_fret if not DLL) + + C subroutine calls: + + aes_rval aes_set_block_size(unsigned int blen, aes_ctx cx[1]); + aes_rval aes_set_encrypt_key(const unsigned char in_key[], + unsigned int klen, aes_ctx cx[1]); + aes_rval aes_encrypt_block(const unsigned char in_blk[], + unsigned char out_blk[], const aes_ctx cx[1]); + + aes_rval aes_dec_len(unsigned int blen, aes_ctx cx[1]); + aes_rval aes_set_decrypt_key(const unsigned char in_key[], + unsigned int klen, aes_ctx cx[1]); + aes_rval aes_decrypt_block(const unsigned char in_blk[], + unsigned char out_blk[], const aes_ctx cx[1]); + + IMPORTANT NOTE: If you are using this C interface and your compiler does + not set the memory used for objects to zero before use, you will need to + ensure that cx.n_blk is set to zero before using these subroutine calls. + + C++ aes class subroutines: + + class AESclass for encryption + class AESclass for decryption + + aes_rval len(unsigned int blen = 16); + aes_rval key(const unsigned char in_key[], unsigned int klen); + aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]); + + aes_rval len(unsigned int blen = 16); + aes_rval key(const unsigned char in_key[], unsigned int klen); + aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]); + + The block length inputs to set_block and set_key are in numbers of + BYTES, not bits. The calls to subroutines must be made in the above + order but multiple calls can be made without repeating earlier calls + if their parameters have not changed. If the cipher block length is + variable but set_blk has not been called before cipher operations a + value of 16 is assumed (that is, the AES block size). In contrast to + earlier versions the block and key length parameters are now checked + for correctness and the encryption and decryption routines check to + ensure that an appropriate key has been set before they are called. + + COMPILATION + + The files used to provide AES (Rijndael) are + + a. aes.h for the definitions needed for use in C. + b. aescpp.h for the definitions needed for use in C++. + c. aesopt.h for setting compilation options (also includes common + code). + d. aescrypt.c for encryption and decrytpion, or + e. aescrypt.asm for encryption and decryption using assembler code. + f. aeskey.c for key scheduling. + g. aestab.c for table loading or generation. + + The assembler code uses the NASM assembler. The above files provice + block and key lengths of 16, 24 and 32 bytes (128, 192 and 256 bits). + If aescrypp.c and aeskeypp.c are used instead of aescrypt.c and + aeskey.c respectively, the block and key lengths can then be 16, 20, + 24, 28 or 32 bytes. However this code has not been optimised to the + same extent and is hence slower (esepcially for the AES block size + of 16 bytes). + + To compile AES (Rijndael) for use in C code use aes.h and exclude + the AES_DLL define in aes.h + + To compile AES (Rijndael) for use in in C++ code use aescpp.h and + exclude the AES_DLL define in aes.h + + To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use + aes.h, include the AES_DLL define and compile the DLL. If using + the test files to test the DLL, exclude aes.c from the test build + project and compile it with the same defines as used for the DLL + (ensure that the DLL path is correct) + + CONFIGURATION OPTIONS (here and in aes.h) + + a. define BLOCK_SIZE in aes.h to set the cipher block size (16, 24 + or 32 for the standard code, or 16, 20, 24, 28 or 32 for the + extended code) or leave this undefined for dynamically variable + block size (this will result in much slower code). + b. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL + c. You may need to set PLATFORM_BYTE_ORDER to define the byte order. + d. If you want the code to run in a specific internal byte order, then + INTERNAL_BYTE_ORDER must be set accordingly. + e. set other configuration options decribed below. +*/ + +#ifndef _AESOPT_H +#define _AESOPT_H + +#if defined(__cplusplus) +extern "C" +{ +#if 0 +} +#endif +#endif + +/* START OF CONFIGURATION OPTIONS + + USE OF DEFINES + + Later in this section there are a number of defines that control the + operation of the code. In each section, the purpose of each define is + explained so that the relevant form can be included or excluded by + setting either 1's or 0's respectively on the branches of the related + #if clauses. +*/ + +/* DO NOT CHANGE THE FOLLOWING EIGHT DEFINES */ + +#define NO_TABLES 0 +#define ONE_TABLE 1 +#define FOUR_TABLES 4 +#define NONE 0 +#define PARTIAL 1 +#define FULL 2 +#define AES_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define AES_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +/* 1. PLATFORM SPECIFIC INCLUDES */ + +#include "aes.h" + +#include "config.h" + +#if defined(WORDS_BIGENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +#else +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +#endif + +/* 2. BYTE ORDER IN 32-BIT WORDS + + To obtain the highest speed on processors with 32-bit words, this code + needs to determine the order in which bytes are packed into such words. + The following block of code is an attempt to capture the most obvious + ways in which various environemnts define byte order. It may well fail, + in which case the definitions will need to be set by editing at the + points marked **** EDIT HERE IF NECESSARY **** below. +*/ +#if !defined(PLATFORM_BYTE_ORDER) +#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN) +# if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# if defined(BYTE_ORDER) +# if (BYTE_ORDER == LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif (BYTE_ORDER == BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +# endif +# elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN) +# if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# if defined(_BYTE_ORDER) +# if (_BYTE_ORDER == _LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif (_BYTE_ORDER == _BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +# endif +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +#define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +#elif (('1234' >> 24) == '1') +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +#elif (('4321' >> 24) == '1') +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +#endif +#endif + +#if !defined(PLATFORM_BYTE_ORDER) +# error Please set undetermined byte order (lines 241 or 243 of aesopt.h). +#endif + +/* 3. FUNCTIONS REQUIRED + + This implementation provides five main subroutines which provide for + setting block length, setting encryption and decryption keys and for + encryption and decryption. When the assembler code is not being used + the following definition blocks allow the selection of the routines + that are to be included in the compilation. +*/ +#if 1 +#define ENCRYPTION +#define ENCRYPTION_KEY_SCHEDULE +#endif + +#if 0 +#define DECRYPTION +#define DECRYPTION_KEY_SCHEDULE +#endif + +/* 4. ASSEMBLER SUPPORT + + This define (which can be on the command line) enables the use of the + assembler code routines for encryption and decryption with the C code + only providing key scheduling +*/ +#if 0 +#define AES_ASM +#endif + +/* 5. BYTE ORDER WITHIN 32 BIT WORDS + + The fundamental data processing units in Rijndael are 8-bit bytes. The + input, output and key input are all enumerated arrays of bytes in which + bytes are numbered starting at zero and increasing to one less than the + number of bytes in the array in question. This enumeration is only used + for naming bytes and does not imply any adjacency or order relationship + from one byte to another. When these inputs and outputs are considered + as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to + byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. + In this implementation bits are numbered from 0 to 7 starting at the + numerically least significant end of each byte (bit n represents 2^n). + + However, Rijndael can be implemented more efficiently using 32-bit + words by packing bytes into words so that bytes 4*n to 4*n+3 are placed + into word[n]. While in principle these bytes can be assembled into words + in any positions, this implementation only supports the two formats in + which bytes in adjacent positions within words also have adjacent byte + numbers. This order is called big-endian if the lowest numbered bytes + in words have the highest numeric significance and little-endian if the + opposite applies. + + This code can work in either order irrespective of the order used by the + machine on which it runs. Normally the internal byte order will be set + to the order of the processor on which the code is to be run but this + define can be used to reverse this in special situations +*/ +#if 1 +#define INTERNAL_BYTE_ORDER PLATFORM_BYTE_ORDER +#elif 0 +#define INTERNAL_BYTE_ORDER AES_LITTLE_ENDIAN +#elif 0 +#define INTERNAL_BYTE_ORDER AES_BIG_ENDIAN +#else +#error The internal byte order is not defined +#endif + +/* 6. FAST INPUT/OUTPUT OPERATIONS. + + On some machines it is possible to improve speed by transferring the + bytes in the input and output arrays to and from the internal 32-bit + variables by addressing these arrays as if they are arrays of 32-bit + words. On some machines this will always be possible but there may + be a large performance penalty if the byte arrays are not aligned on + the normal word boundaries. On other machines this technique will + lead to memory access errors when such 32-bit word accesses are not + properly aligned. The option SAFE_IO avoids such problems but will + often be slower on those machines that support misaligned access + (especially so if care is taken to align the input and output byte + arrays on 32-bit word boundaries). If SAFE_IO is not defined it is + assumed that access to byte arrays as if they are arrays of 32-bit + words will not cause problems when such accesses are misaligned. +*/ +#if 1 && !defined(_MSC_VER) +#define SAFE_IO +#endif + +/* 7. LOOP UNROLLING + + The code for encryption and decrytpion cycles through a number of rounds + that can be implemented either in a loop or by expanding the code into a + long sequence of instructions, the latter producing a larger program but + one that will often be much faster. The latter is called loop unrolling. + There are also potential speed advantages in expanding two iterations in + a loop with half the number of iterations, which is called partial loop + unrolling. The following options allow partial or full loop unrolling + to be set independently for encryption and decryption +*/ +#if 1 +#define ENC_UNROLL FULL +#elif 0 +#define ENC_UNROLL PARTIAL +#else +#define ENC_UNROLL NONE +#endif + +#if 1 +#define DEC_UNROLL FULL +#elif 0 +#define DEC_UNROLL PARTIAL +#else +#define DEC_UNROLL NONE +#endif + +/* 8. FAST FINITE FIELD OPERATIONS + + If this section is included, tables are used to provide faster finite + field arithmetic (this has no effect if FIXED_TABLES is defined). +*/ +#if 1 +#define FF_TABLES +#endif + +/* 9. INTERNAL STATE VARIABLE FORMAT + + The internal state of Rijndael is stored in a number of local 32-bit + word varaibles which can be defined either as an array or as individual + names variables. Include this section if you want to store these local + varaibles in arrays. Otherwise individual local variables will be used. +*/ +#if 1 +#define ARRAYS +#endif + +/* In this implementation the columns of the state array are each held in + 32-bit words. The state array can be held in various ways: in an array + of words, in a number of individual word variables or in a number of + processor registers. The following define maps a variable name x and + a column number c to the way the state array variable is to be held. + The first define below maps the state into an array x[c] whereas the + second form maps the state into a number of individual variables x0, + x1, etc. Another form could map individual state colums to machine + register names. +*/ + +#if defined(ARRAYS) +#define s(x,c) x[c] +#else +#define s(x,c) x##c +#endif + +/* 10. VARIABLE BLOCK SIZE SPEED + + This section is only relevant if you wish to use the variable block + length feature of the code. Include this section if you place more + emphasis on speed rather than code size. +*/ +#if 1 +#define FAST_VARIABLE +#endif + +/* 11. FIXED OR DYNAMIC TABLES + + When this section is included the tables used by the code are comipled + statically into the binary file. Otherwise they are computed once when + the code is first used. +*/ +#if 1 +#define FIXED_TABLES +#endif + +/* 12. GLOBAL VARIABLES + + In some circumstances global variables to hold the fixed tables are not + possible so the tables have to be placed in a structure that is passed + around at run time through the AES API calls. In this case FIXED_TABLES + cannot be used. GLOBALS must be defined in order to use the assembler + version of this code. If GLOBALS is not defined, then AES_TABLE_PTR must + be defined either on the command line or early in aes.h in order to + provide space for the table pointer in the AES context. +*/ +#if 1 || defined(AES_ASM) +#define GLOBALS +#elif !defined(AES_TABLE_PTR) +#error no context space for table pointer (compile with AES_TABLE_PTR defined) +#elif defined(FIXED_TABLES) +#undef FIXED_TABLES +#endif + +/* 13. INTERNAL TABLE CONFIGURATION + + This cipher proceeds by repeating in a number of cycles known as 'rounds' + which are implemented by a round function which can optionally be speeded + up using tables. The basic tables are each 256 32-bit words, with either + one or four tables being required for each round function depending on + how much speed is required. The encryption and decryption round functions + are different and the last encryption and decrytpion round functions are + different again making four different round functions in all. + + This means that: + 1. Normal encryption and decryption rounds can each use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + 2. The last encryption and decryption rounds can also use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + + Include or exclude the appropriate definitions below to set the number + of tables used by this implementation. +*/ + +#if 1 /* set tables for the normal encryption round */ +#define ENC_ROUND FOUR_TABLES +#elif 0 +#define ENC_ROUND ONE_TABLE +#else +#define ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last encryption round */ +#define LAST_ENC_ROUND FOUR_TABLES +#elif 0 +#define LAST_ENC_ROUND ONE_TABLE +#else +#define LAST_ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the normal decryption round */ +#define DEC_ROUND FOUR_TABLES +#elif 0 +#define DEC_ROUND ONE_TABLE +#else +#define DEC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last decryption round */ +#define LAST_DEC_ROUND FOUR_TABLES +#elif 0 +#define LAST_DEC_ROUND ONE_TABLE +#else +#define LAST_DEC_ROUND NO_TABLES +#endif + +/* The decryption key schedule can be speeded up with tables in the same + way that the round functions can. Include or exclude the following + defines to set this requirement. +*/ +#if 1 +#define KEY_SCHED FOUR_TABLES +#elif 0 +#define KEY_SCHED ONE_TABLE +#else +#define KEY_SCHED NO_TABLES +#endif + +/* END OF CONFIGURATION OPTIONS */ + +#if defined(BLOCK_SIZE) && ((BLOCK_SIZE & 3) || BLOCK_SIZE < 16 || BLOCK_SIZE > 32) +#error An illegal block size has been specified. +#endif + +#if !defined(BLOCK_SIZE) +#define RC_LENGTH 29 +#else +#define RC_LENGTH (5 * BLOCK_SIZE / 4 - (BLOCK_SIZE == 16 ? 10 : 11)) +#endif + +/* Disable at least some poor combinations of options */ + +#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND NO_TABLES +#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND ONE_TABLE +#endif + +#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE +#undef ENC_UNROLL +#define ENC_UNROLL NONE +#endif + +#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND NO_TABLES +#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND ONE_TABLE +#endif + +#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE +#undef DEC_UNROLL +#define DEC_UNROLL NONE +#endif + +/* upr(x,n): rotates bytes within words by n positions, moving bytes to + higher index positions with wrap around into low positions + ups(x,n): moves bytes by n positions to higher index positions in + words but without wrap around + bval(x,n): extracts a byte from a word + + NOTE: The definitions given here are intended only for use with + unsigned variables and with shift counts that are compile + time constants +*/ + +#if (INTERNAL_BYTE_ORDER == AES_LITTLE_ENDIAN) +#define upr(x,n) (((aes_32t)(x) << (8 * (n))) | ((aes_32t)(x) >> (32 - 8 * (n)))) +#define ups(x,n) ((aes_32t) (x) << (8 * (n))) +#define bval(x,n) ((aes_08t)((x) >> (8 * (n)))) +#define bytes2word(b0, b1, b2, b3) \ + (((aes_32t)(b3) << 24) | ((aes_32t)(b2) << 16) | ((aes_32t)(b1) << 8) | (b0)) +#endif + +#if (INTERNAL_BYTE_ORDER == AES_BIG_ENDIAN) +#define upr(x,n) (((aes_32t)(x) >> (8 * (n))) | ((aes_32t)(x) << (32 - 8 * (n)))) +#define ups(x,n) ((aes_32t) (x) >> (8 * (n)))) +#define bval(x,n) ((aes_08t)((x) >> (24 - 8 * (n)))) +#define bytes2word(b0, b1, b2, b3) \ + (((aes_32t)(b0) << 24) | ((aes_32t)(b1) << 16) | ((aes_32t)(b2) << 8) | (b3)) +#endif + +#if defined(SAFE_IO) + +#define word_in(x) bytes2word((x)[0], (x)[1], (x)[2], (x)[3]) +#define word_out(x,v) { (x)[0] = bval(v,0); (x)[1] = bval(v,1); \ + (x)[2] = bval(v,2); (x)[3] = bval(v,3); } + +#elif (INTERNAL_BYTE_ORDER == PLATFORM_BYTE_ORDER) + +#define word_in(x) (*(aes_32t*)(x)) +#define word_out(x,v) (*(aes_32t*)(x) = (v)) + +#else + +#if !defined(bswap_32) +#define brot(x,n) (((aes_32t)(x) << n) | ((aes_32t)(x) >> (32 - n))) +#define bswap_32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00)) +#endif + +#define word_in(x) bswap_32(*(aes_32t*)(x)) +#define word_out(x,v) (*(aes_32t*)(x) = bswap_32(v)) + +#endif + +/* the finite field modular polynomial and elements */ + +#define WPOLY 0x011b +#define BPOLY 0x1b + +/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + +#define m1 0x80808080 +#define m2 0x7f7f7f7f +#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) + +/* The following defines provide alternative definitions of FFmulX that might + give improved performance if a fast 32-bit multiply is not available. Note + that a temporary variable u needs to be defined where FFmulX is used. + +#define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) +#define m4 (0x01010101 * BPOLY) +#define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) +*/ + +/* Work out which tables are needed for the different options */ + +#ifdef AES_ASM +#ifdef ENC_ROUND +#undef ENC_ROUND +#endif +#define ENC_ROUND FOUR_TABLES +#ifdef LAST_ENC_ROUND +#undef LAST_ENC_ROUND +#endif +#define LAST_ENC_ROUND FOUR_TABLES +#ifdef DEC_ROUND +#undef DEC_ROUND +#endif +#define DEC_ROUND FOUR_TABLES +#ifdef LAST_DEC_ROUND +#undef LAST_DEC_ROUND +#endif +#define LAST_DEC_ROUND FOUR_TABLES +#ifdef KEY_SCHED +#undef KEY_SCHED +#define KEY_SCHED FOUR_TABLES +#endif +#endif + +#if defined(ENCRYPTION) || defined(AES_ASM) +#if ENC_ROUND == ONE_TABLE +#define FT1_SET +#elif ENC_ROUND == FOUR_TABLES +#define FT4_SET +#else +#define SBX_SET +#endif +#if LAST_ENC_ROUND == ONE_TABLE +#define FL1_SET +#elif LAST_ENC_ROUND == FOUR_TABLES +#define FL4_SET +#elif !defined(SBX_SET) +#define SBX_SET +#endif +#endif + +#if defined(DECRYPTION) || defined(AES_ASM) +#if DEC_ROUND == ONE_TABLE +#define IT1_SET +#elif DEC_ROUND == FOUR_TABLES +#define IT4_SET +#else +#define ISB_SET +#endif +#if LAST_DEC_ROUND == ONE_TABLE +#define IL1_SET +#elif LAST_DEC_ROUND == FOUR_TABLES +#define IL4_SET +#elif !defined(ISB_SET) +#define ISB_SET +#endif +#endif + +#if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE) +#if KEY_SCHED == ONE_TABLE +#define LS1_SET +#define IM1_SET +#elif KEY_SCHED == FOUR_TABLES +#define LS4_SET +#define IM4_SET +#elif !defined(SBX_SET) +#define SBX_SET +#endif +#endif + +/* If there are no global variables, the AES tables are placed in + a structure and a pointer is added to the AES context. If this + facility is used, the calling program has to ensure that this + pointer is managed appropriately. In particular, the value of + the t_dec(in,it) item in the table structure must be set to zero + in order to ensure that the tables are initialised. In practice + the three code sequences in aeskey.c that control the calls to + gen_tabs() and the gen_tabs() routine itself will require some + changes for a specific implementation. If global variables are + available it will generally be preferable to use them with the + precomputed FIXED_TABLES option that uses static global tables. + + The following defines can be used to control the way the tables + are defined, initialised and used in embedded environments that + require special features for these purposes + + the 't_dec' construction is used to declare fixed table arrays + the 't_set' construction is used to set fixed table values + the 't_use' construction is used to access fixed table values + + 256 byte tables: + + t_xxx(s,box) => forward S box + t_xxx(i,box) => inverse S box + + 256 32-bit word OR 4 x 256 32-bit word tables: + + t_xxx(f,n) => forward normal round + t_xxx(f,l) => forward last round + t_xxx(i,n) => inverse normal round + t_xxx(i,l) => inverse last round + t_xxx(l,s) => key schedule table + t_xxx(i,m) => key schedule table + + Other variables and tables: + + t_xxx(in,it) => the table initialsation flag + t_xxx(r,c) => the rcon table +*/ + +#define t_dec(m,n) t_##m##n +#define t_set(m,n) t_##m##n /* may be redefined once below */ +#define t_use(m,n) t_##m##n /* may be redefined once below */ + +#ifdef FIXED_TABLES + +#define prefx INTERNAL const +#elif defined(GLOBALS) +#define prefx extern +extern aes_08t t_dec(in,it); +void gen_tabs(void); +#else +#define prefx +void gen_tabs(aes_ctx cx[1]); + +typedef struct { +#endif + +prefx aes_32t t_dec(r,c)[RC_LENGTH]; + +#ifdef SBX_SET +prefx aes_08t t_dec(s,box)[256]; +#endif + +#ifdef ISB_SET +prefx aes_08t t_dec(i,box)[256]; +#endif + +#ifdef FT1_SET +prefx aes_32t t_dec(f,n)[256]; +#endif + +#ifdef FT4_SET +prefx aes_32t t_dec(f,n)[4][256]; +#endif + +#ifdef FL1_SET +prefx aes_32t t_dec(f,l)[256]; +#endif + +#ifdef FL4_SET +prefx aes_32t t_dec(f,l)[4][256]; +#endif + +#ifdef IT1_SET +prefx aes_32t t_dec(i,n)[256]; +#endif + +#ifdef IT4_SET +prefx aes_32t t_dec(i,n)[4][256]; +#endif + +#ifdef IL1_SET +prefx aes_32t t_dec(i,l)[256]; +#endif + +#ifdef IL4_SET +prefx aes_32t t_dec(i,l)[4][256]; +#endif + +#ifdef LS1_SET +#ifdef FL1_SET +#undef LS1_SET +#else +prefx aes_32t t_dec(l,s)[256]; +#endif +#endif + +#ifdef LS4_SET +#ifdef FL4_SET +#undef LS4_SET +#else +prefx aes_32t t_dec(l,s)[4][256]; +#endif +#endif + +#ifdef IM1_SET +prefx aes_32t t_dec(i,m)[256]; +#endif + +#ifdef IM4_SET +prefx aes_32t t_dec(i,m)[4][256]; +#endif + +prefx aes_08t t_dec(in,it); + +#ifndef GLOBALS +} s_ty; + +extern s_ty s_t; + +/* modify the table set macro to cope with a static structure */ +#undef t_set +#define t_set(m,n) (s_t.t_##m##n) + +/* modify the table use macro to cope with a context pointer */ +#undef t_use +#define t_use(m,n) (((s_ty*)cx->t_ptr)->t_##m##n) + +#endif + +/* Set the number of columns in nc. Note that it is important + that nc is a constant which is known at compile time if the + highest speed version of the code is needed. +*/ + +#if defined(BLOCK_SIZE) +#define nc (BLOCK_SIZE >> 2) +#else +#define nc (cx->n_blk >> 2) +#endif + +/* generic definitions of Rijndael macros that use tables */ + +#define no_table(x,box,vf,rf,c) bytes2word( \ + box[bval(vf(x,0,c),rf(0,c))], \ + box[bval(vf(x,1,c),rf(1,c))], \ + box[bval(vf(x,2,c),rf(2,c))], \ + box[bval(vf(x,3,c),rf(3,c))]) + +#define one_table(x,op,tab,vf,rf,c) \ + ( tab[bval(vf(x,0,c),rf(0,c))] \ + ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ + ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ + ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) + +#define four_tables(x,tab,vf,rf,c) \ + ( tab[0][bval(vf(x,0,c),rf(0,c))] \ + ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ + ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ + ^ tab[3][bval(vf(x,3,c),rf(3,c))]) + +#define vf1(x,r,c) (x) +#define rf1(r,c) (r) +#define rf2(r,c) ((8+r-c)&3) + +/* perform forward and inverse column mix operation on four bytes in long word x in */ +/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ + +#define dec_fmvars +#if defined(FM4_SET) /* not currently used */ +#define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) +#elif defined(FM1_SET) /* not currently used */ +#define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) +#else +#undef dec_fmvars +#define dec_fmvars aes_32t f1, f2; +#define fwd_mcol(x) (f1 = (x), f2 = FFmulX(f1), f2 ^ upr(f1 ^ f2, 3) ^ upr(f1, 2) ^ upr(f1, 1)) +#endif + +#define dec_imvars +#if defined(IM4_SET) +#define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) +#elif defined(IM1_SET) +#define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) +#else +#undef dec_imvars +#define dec_imvars aes_32t f2, f4, f8, f9; +#define inv_mcol(x) \ + (f9 = (x), f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ + f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1)) +#endif + +#if defined(FL4_SET) +#define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) +#elif defined(LS4_SET) +#define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) +#elif defined(FL1_SET) +#define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) +#elif defined(LS1_SET) +#define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) +#else +#define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/app/jni/gladman-fcrypt/aestab.c b/app/jni/gladman-fcrypt/aestab.c new file mode 100644 index 0000000..7b202be --- /dev/null +++ b/app/jni/gladman-fcrypt/aestab.c @@ -0,0 +1,529 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file contains the code for generating the fixed tables needed for AES +*/ + +#include "aesopt.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined(FIXED_TABLES) || !defined(FF_TABLES) + +/* finite field arithmetic operations */ + +#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) +#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#endif + +#if defined(FIXED_TABLES) + +#define sb_data(w) \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) + +#define isb_data(w) \ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d), + +#define mm_data(w) \ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) + +#define h0(x) (x) + +/* These defines are used to ensure tables are generated in the + right format depending on the internal byte order required +*/ + +#define w0(p) bytes2word(p, 0, 0, 0) +#define w1(p) bytes2word(0, p, 0, 0) +#define w2(p) bytes2word(0, 0, p, 0) +#define w3(p) bytes2word(0, 0, 0, p) + +/* Number of elements required in this table for different + block and key lengths is: + + Rcon Table key length (bytes) + Length 16 20 24 28 32 + --------------------- + block 16 | 10 9 8 7 7 + length 20 | 14 11 10 9 9 + (bytes) 24 | 19 15 12 11 11 + 28 | 24 19 16 13 13 + 32 | 29 23 19 17 14 + + this table can be a table of bytes if the key schedule + code is adjusted accordingly +*/ + +#define u0(p) bytes2word(f2(p), p, p, f3(p)) +#define u1(p) bytes2word(f3(p), f2(p), p, p) +#define u2(p) bytes2word(p, f3(p), f2(p), p) +#define u3(p) bytes2word(p, p, f3(p), f2(p)) + +#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) +#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) +#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) +#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) + +INTERNAL const aes_32t t_dec(r,c)[RC_LENGTH] = +{ + w0(0x01), w0(0x02), w0(0x04), w0(0x08), w0(0x10), + w0(0x20), w0(0x40), w0(0x80), w0(0x1b), w0(0x36), +#if RC_LENGTH > 10 + w0(0x6c), w0(0xd8), w0(0xab), w0(0x4d), +#endif +#if RC_LENGTH > 14 + w0(0x9a), w0(0x2f), w0(0x5e), w0(0xbc), w0(0x63), +#endif +#if RC_LENGTH > 19 + w0(0xc6), w0(0x97), w0(0x35), w0(0x6a), w0(0xd4), +#endif +#if RC_LENGTH > 24 + w0(0xb3), w0(0x7d), w0(0xfa), w0(0xef), w0(0xc5) +#endif +}; + +#ifdef SBX_SET +INTERNAL const aes_08t t_dec(s,box)[256] = { sb_data(h0) }; +#endif +#ifdef ISB_SET +INTERNAL const aes_08t t_dec(i,box)[256] = { isb_data(h0) }; +#endif + +#ifdef FT1_SET +INTERNAL const aes_32t t_dec(f,n)[256] = { sb_data(u0) }; +#endif +#ifdef FT4_SET +INTERNAL const aes_32t t_dec(f,n)[4][256] = + { { sb_data(u0) }, { sb_data(u1) }, { sb_data(u2) }, { sb_data(u3) } }; +#endif + +#ifdef FL1_SET +INTERNAL const aes_32t t_dec(f,l)[256] = { sb_data(w0) }; +#endif +#ifdef FL4_SET +INTERNAL const aes_32t t_dec(f,l)[4][256] = + { { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } }; +#endif + +#ifdef IT1_SET +INTERNAL const aes_32t t_dec(i,n)[256] = { isb_data(v0) }; +#endif +#ifdef IT4_SET +INTERNAL const aes_32t t_dec(i,n)[4][256] = + { { isb_data(v0) }, { isb_data(v1) }, { isb_data(v2) }, { isb_data(v3) } }; +#endif + +#ifdef IL1_SET +INTERNAL const aes_32t t_dec(i,l)[256] = { isb_data(w0) }; +#endif +#ifdef IL4_SET +INTERNAL const aes_32t t_dec(i,l)[4][256] = + { { isb_data(w0) }, { isb_data(w1) }, { isb_data(w2) }, { isb_data(w3) } }; +#endif + +#ifdef LS1_SET +INTERNAL const aes_32t t_dec(l,s)[256] = { sb_data(w0) }; +#endif +#ifdef LS4_SET +INTERNAL const aes_32t t_dec(l,s)[4][256] = + { { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } }; +#endif + +#ifdef IM1_SET +INTERNAL const aes_32t t_dec(i,m)[256] = { mm_data(v0) }; +#endif +#ifdef IM4_SET +INTERNAL const aes_32t t_dec(i,m)[4][256] = + { { mm_data(v0) }, { mm_data(v1) }, { mm_data(v2) }, { mm_data(v3) } }; +#endif + +#else /* dynamic table generation */ + +#ifdef GLOBALS + +aes_08t t_dec(in,it) = 0; + +aes_32t t_dec(r,c)[RC_LENGTH]; + +#ifdef SBX_SET +aes_08t t_dec(s,box)[256]; +#endif +#ifdef ISB_SET +aes_08t t_dec(i,box)[256]; +#endif + +#ifdef FT1_SET +aes_32t t_dec(f,n)[256]; +#endif +#ifdef FT4_SET +aes_32t t_dec(f,n)[4][256]; +#endif + +#ifdef FL1_SET +aes_32t t_dec(f,l)[256]; +#endif +#ifdef FL4_SET +aes_32t t_dec(f,l)[4][256]; +#endif + +#ifdef IT1_SET +aes_32t t_dec(i,n)[256]; +#endif +#ifdef IT4_SET +aes_32t t_dec(i,n)[4][256]; +#endif + +#ifdef IL1_SET +aes_32t t_dec(i,l)[256]; +#endif +#ifdef IL4_SET +aes_32t t_dec(i,l)[4][256]; +#endif + +#ifdef LS1_SET +aes_32t t_dec(l,s)[256]; +#endif +#ifdef LS4_SET +aes_32t t_dec(l,s)[4][256]; +#endif + +#ifdef IM1_SET +aes_32t t_dec(i,m)[256]; +#endif +#ifdef IM4_SET +aes_32t t_dec(i,m)[4][256]; +#endif + +#else +s_ty s_t; +#endif + +#if !defined(FF_TABLES) + +/* Generate the tables for the dynamic table option + + It will generally be sensible to use tables to compute finite + field multiplies and inverses but where memory is scarse this + code might sometimes be better. But it only has effect during + initialisation so its pretty unimportant in overall terms. +*/ + +/* return 2 ^ (n - 1) where n is the bit number of the highest bit + set in x with x in the range 1 < x < 0x00000200. This form is + used so that locals within fi can be bytes rather than words +*/ + +static aes_08t hibit(const aes_32t x) +{ aes_08t r = (aes_08t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static aes_08t fi(const aes_08t x) +{ aes_08t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if(x < 2) return x; + + for(;;) + { + if(!n1) return v1; + + while(n2 >= n1) + { + n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); + } + + if(!n2) return v2; + + while(n1 >= n2) + { + n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); + } + } +} + +#else + +/* define the finite field multiplies required for Rijndael */ + +#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) +#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) +#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) +#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) +#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) +#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) +#define fi(x) ((x) ? pow[255 - log[x]]: 0) + +#endif + +/* The forward and inverse affine transformations used in the S-box */ + +#define fwd_affine(x) \ + (w = (aes_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(aes_08t)(w^(w>>8))) + +#define inv_affine(x) \ + (w = (aes_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(aes_08t)(w^(w>>8))) + +#ifdef GLOBALS +INTERNAL void gen_tabs(void) +#else +INTERNAL void gen_tabs(aes_ctx cx[1]) +#endif +{ aes_32t i, w; + +#if defined(FF_TABLES) + + aes_08t pow[512], log[256]; + + /* log and power tables for GF(2^8) finite field with + WPOLY as modular polynomial - the simplest primitive + root is 0x03, used here to generate the tables + */ + + i = 0; w = 1; + do + { + pow[i] = (aes_08t)w; + pow[i + 255] = (aes_08t)w; + log[w] = (aes_08t)i++; + w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); + } + while (w != 1); + +#endif + +#ifndef GLOBALS + if(!cx->t_ptr) + cx->t_ptr = &s_t; +#endif + + for(i = 0, w = 1; i < RC_LENGTH; ++i) + { + t_set(r,c)[i] = bytes2word(w, 0, 0, 0); + w = f2(w); + } + + for(i = 0; i < 256; ++i) + { aes_08t b; + + b = fwd_affine(fi((aes_08t)i)); + w = bytes2word(f2(b), b, b, f3(b)); + +#ifdef SBX_SET + t_set(s,box)[i] = b; +#endif + +#ifdef FT1_SET /* tables for a normal encryption round */ + t_set(f,n)[i] = w; +#endif +#ifdef FT4_SET + t_set(f,n)[0][i] = w; + t_set(f,n)[1][i] = upr(w,1); + t_set(f,n)[2][i] = upr(w,2); + t_set(f,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); + +#ifdef FL1_SET /* tables for last encryption round (may also */ + t_set(f,l)[i] = w; /* be used in the key schedule) */ +#endif +#ifdef FL4_SET + t_set(f,l)[0][i] = w; + t_set(f,l)[1][i] = upr(w,1); + t_set(f,l)[2][i] = upr(w,2); + t_set(f,l)[3][i] = upr(w,3); +#endif + +#ifdef LS1_SET /* table for key schedule if t_set(f,l) above is */ + t_set(l,s)[i] = w; /* not of the required form */ +#endif +#ifdef LS4_SET + t_set(l,s)[0][i] = w; + t_set(l,s)[1][i] = upr(w,1); + t_set(l,s)[2][i] = upr(w,2); + t_set(l,s)[3][i] = upr(w,3); +#endif + + b = fi(inv_affine((aes_08t)i)); + w = bytes2word(fe(b), f9(b), fd(b), fb(b)); + +#ifdef IM1_SET /* tables for the inverse mix column operation */ + t_set(i,m)[b] = w; +#endif +#ifdef IM4_SET + t_set(i,m)[0][b] = w; + t_set(i,m)[1][b] = upr(w,1); + t_set(i,m)[2][b] = upr(w,2); + t_set(i,m)[3][b] = upr(w,3); +#endif + +#ifdef ISB_SET + t_set(i,box)[i] = b; +#endif +#ifdef IT1_SET /* tables for a normal decryption round */ + t_set(i,n)[i] = w; +#endif +#ifdef IT4_SET + t_set(i,n)[0][i] = w; + t_set(i,n)[1][i] = upr(w,1); + t_set(i,n)[2][i] = upr(w,2); + t_set(i,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); +#ifdef IL1_SET /* tables for last decryption round */ + t_set(i,l)[i] = w; +#endif +#ifdef IL4_SET + t_set(i,l)[0][i] = w; + t_set(i,l)[1][i] = upr(w,1); + t_set(i,l)[2][i] = upr(w,2); + t_set(i,l)[3][i] = upr(w,3); +#endif + } + + t_set(in,it) = 1; +} + +#endif + +#if defined(__cplusplus) +} +#endif + diff --git a/app/jni/gladman-fcrypt/fileenc.c b/app/jni/gladman-fcrypt/fileenc.c new file mode 100644 index 0000000..a96083b --- /dev/null +++ b/app/jni/gladman-fcrypt/fileenc.c @@ -0,0 +1,144 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + ------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file implements password based file encryption and authentication + using AES in CTR mode, HMAC-SHA1 authentication and RFC2898 password + based key derivation. + +*/ + +#include + +#include "fileenc.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* subroutine for data encryption/decryption */ +/* this could be speeded up a lot by aligning */ +/* buffers and using 32 bit operations */ + +static void encr_data(unsigned char data[], unsigned long d_len, fcrypt_ctx cx[1]) + { unsigned long i = 0; + unsigned int pos = cx->encr_pos; + + while(i < d_len) + { + if(pos == BLOCK_SIZE) + { unsigned int j = 0; + /* increment encryption nonce */ + while(j < 8 && !++cx->nonce[j]) + ++j; + /* encrypt the nonce to form next xor buffer */ + aes_encrypt_block(cx->nonce, cx->encr_bfr, cx->encr_ctx); + pos = 0; + } + + data[i++] ^= cx->encr_bfr[pos++]; + } + + cx->encr_pos = pos; +} + +int _zip_fcrypt_init( + unsigned int mode, /* the mode to be used (input) */ + const unsigned char pwd[], /* the user specified password (input) */ + unsigned int pwd_len, /* the length of the password (input) */ + const unsigned char salt[], /* the salt (input) */ +#ifdef PASSWORD_VERIFIER + unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ +#endif + fcrypt_ctx cx[1]) /* the file encryption context (output) */ +{ unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH]; + + if(pwd_len > MAX_PWD_LENGTH) + return PASSWORD_TOO_LONG; + + if(mode < 1 || mode > 3) + return BAD_MODE; + + cx->mode = mode; + cx->pwd_len = pwd_len; + + /* derive the encryption and authetication keys and the password verifier */ + derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS, + kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH); + + /* initialise the encryption nonce and buffer pos */ + cx->encr_pos = BLOCK_SIZE; + /* if we need a random component in the encryption */ + /* nonce, this is where it would have to be set */ + memset(cx->nonce, 0, BLOCK_SIZE * sizeof(unsigned char)); + + /* initialise for encryption using key 1 */ + aes_set_encrypt_key(kbuf, KEY_LENGTH(mode), cx->encr_ctx); + + /* initialise for authentication using key 2 */ + hmac_sha1_begin(cx->auth_ctx); + hmac_sha1_key(kbuf + KEY_LENGTH(mode), KEY_LENGTH(mode), cx->auth_ctx); + +#ifdef PASSWORD_VERIFIER + memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH); +#endif + + return GOOD_RETURN; +} + +/* perform 'in place' encryption and authentication */ + +void _zip_fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]) +{ + encr_data(data, data_len, cx); + hmac_sha1_data(data, data_len, cx->auth_ctx); +} + +/* perform 'in place' authentication and decryption */ + +void _zip_fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]) +{ + hmac_sha1_data(data, data_len, cx->auth_ctx); + encr_data(data, data_len, cx); +} + +/* close encryption/decryption and return the MAC value */ + +int _zip_fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1]) +{ + hmac_sha1_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx); + return MAC_LENGTH(cx->mode); /* return MAC length in bytes */ +} + +#if defined(__cplusplus) +} +#endif diff --git a/app/jni/gladman-fcrypt/fileenc.h b/app/jni/gladman-fcrypt/fileenc.h new file mode 100644 index 0000000..d7b5234 --- /dev/null +++ b/app/jni/gladman-fcrypt/fileenc.h @@ -0,0 +1,121 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file contains the header file for fileenc.c, which implements password + based file encryption and authentication using AES in CTR mode, HMAC-SHA1 + authentication and RFC2898 password based key derivation. +*/ + +#ifndef _FENC_H +#define _FENC_H + +#include "aes.h" +#include "hmac.h" +#include "pwd2key.h" + +#define PASSWORD_VERIFIER + +#define MAX_KEY_LENGTH 32 +#define MAX_PWD_LENGTH 128 +#define MAX_SALT_LENGTH 16 +#define KEYING_ITERATIONS 1000 + +#ifdef PASSWORD_VERIFIER +#define PWD_VER_LENGTH 2 +#else +#define PWD_VER_LENGTH 0 +#endif + +#define GOOD_RETURN 0 +#define PASSWORD_TOO_LONG -100 +#define BAD_MODE -101 + +/* + Field lengths (in bytes) versus File Encryption Mode (0 < mode < 4) + + Mode Key Salt MAC Overhead + 1 16 8 10 18 + 2 24 12 10 22 + 3 32 16 10 26 + + The following macros assume that the mode value is correct. +*/ + +#define KEY_LENGTH(mode) (8 * (mode & 3) + 8) +#define SALT_LENGTH(mode) (4 * (mode & 3) + 4) +#define MAC_LENGTH(mode) (10) + +/* the context for file encryption */ + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef struct +{ unsigned char nonce[BLOCK_SIZE]; /* the CTR nonce */ + unsigned char encr_bfr[BLOCK_SIZE]; /* encrypt buffer */ + aes_ctx encr_ctx[1]; /* encryption context */ + hmac_ctx auth_ctx[1]; /* authentication context */ + unsigned int encr_pos; /* block position (enc) */ + unsigned int pwd_len; /* password length */ + unsigned int mode; /* File encryption mode */ +} fcrypt_ctx; + +/* initialise file encryption or decryption */ + +int _zip_fcrypt_init( + unsigned int mode, /* the mode to be used (input) */ + const unsigned char pwd[], /* the user specified password (input) */ + unsigned int pwd_len, /* the length of the password (input) */ + const unsigned char salt[], /* the salt (input) */ +#ifdef PASSWORD_VERIFIER + unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */ +#endif + fcrypt_ctx cx[1]); /* the file encryption context (output) */ + +/* perform 'in place' encryption or decryption and authentication */ + +void _zip_fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]); +void _zip_fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]); + +/* close encryption/decryption and return the MAC value */ +/* the return value is the length of the MAC */ + +int _zip_fcrypt_end(unsigned char mac[], /* the MAC value (output) */ + fcrypt_ctx cx[1]); /* the context (input) */ + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/app/jni/gladman-fcrypt/hmac.c b/app/jni/gladman-fcrypt/hmac.c new file mode 100644 index 0000000..d031a9d --- /dev/null +++ b/app/jni/gladman-fcrypt/hmac.c @@ -0,0 +1,150 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This is an implementation of HMAC, the FIPS standard keyed hash function +*/ + +#include "hmac.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* initialise the HMAC context to zero */ +INTERNAL void hmac_sha1_begin(hmac_ctx cx[1]) +{ + memset(cx, 0, sizeof(hmac_ctx)); +} + +/* input the HMAC key (can be called multiple times) */ +INTERNAL int hmac_sha1_key(const unsigned char key[], unsigned int key_len, hmac_ctx cx[1]) +{ + if(cx->klen == HMAC_IN_DATA) /* error if further key input */ + return HMAC_BAD_MODE; /* is attempted in data mode */ + + if(cx->klen + key_len > IN_BLOCK_LENGTH) /* if the key has to be hashed */ + { + if(cx->klen <= IN_BLOCK_LENGTH) /* if the hash has not yet been */ + { /* started, initialise it and */ + sha1_begin(cx->ctx); /* hash stored key characters */ + sha1_hash(cx->key, cx->klen, cx->ctx); + } + + sha1_hash(key, key_len, cx->ctx); /* hash long key data into hash */ + } + else /* otherwise store key data */ + memcpy(cx->key + cx->klen, key, key_len); + + cx->klen += key_len; /* update the key length count */ + return HMAC_OK; +} + +/* input the HMAC data (can be called multiple times) - */ +/* note that this call terminates the key input phase */ +INTERNAL void hmac_sha1_data(const unsigned char data[], unsigned int data_len, hmac_ctx cx[1]) +{ unsigned int i; + + if(cx->klen != HMAC_IN_DATA) /* if not yet in data phase */ + { + if(cx->klen > IN_BLOCK_LENGTH) /* if key is being hashed */ + { /* complete the hash and */ + sha1_end(cx->key, cx->ctx); /* store the result as the */ + cx->klen = OUT_BLOCK_LENGTH; /* key and set new length */ + } + + /* pad the key if necessary */ + if (cx->klen < IN_BLOCK_LENGTH) + { + memset(cx->key + cx->klen, 0, IN_BLOCK_LENGTH - cx->klen); + } + + /* xor ipad into key value */ + for(i = 0; i < (IN_BLOCK_LENGTH >> 2); ++i) + ((sha1_32t*)cx->key)[i] ^= 0x36363636; + + /* and start hash operation */ + sha1_begin(cx->ctx); + sha1_hash(cx->key, IN_BLOCK_LENGTH, cx->ctx); + + /* mark as now in data mode */ + cx->klen = HMAC_IN_DATA; + } + + /* hash the data (if any) */ + if(data_len) + sha1_hash(data, data_len, cx->ctx); +} + +/* compute and output the MAC value */ +INTERNAL void hmac_sha1_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1]) +{ unsigned char dig[OUT_BLOCK_LENGTH]; + unsigned int i; + + /* if no data has been entered perform a null data phase */ + if(cx->klen != HMAC_IN_DATA) + hmac_sha1_data((const unsigned char*)0, 0, cx); + + sha1_end(dig, cx->ctx); /* complete the inner hash */ + + /* set outer key value using opad and removing ipad */ + for(i = 0; i < (IN_BLOCK_LENGTH >> 2); ++i) + ((sha1_32t*)cx->key)[i] ^= 0x36363636 ^ 0x5c5c5c5c; + + /* perform the outer hash operation */ + sha1_begin(cx->ctx); + sha1_hash(cx->key, IN_BLOCK_LENGTH, cx->ctx); + sha1_hash(dig, OUT_BLOCK_LENGTH, cx->ctx); + sha1_end(dig, cx->ctx); + + /* output the hash value */ + for(i = 0; i < mac_len; ++i) + mac[i] = dig[i]; +} + +#if 0 /* not used */ +/* 'do it all in one go' subroutine */ +INTERNAL void hmac_sha1(const unsigned char key[], unsigned int key_len, + const unsigned char data[], unsigned int data_len, + unsigned char mac[], unsigned int mac_len) +{ hmac_ctx cx[1]; + + hmac_sha1_begin(cx); + hmac_sha1_key(key, key_len, cx); + hmac_sha1_data(data, data_len, cx); + hmac_sha1_end(mac, mac_len, cx); +} +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/app/jni/gladman-fcrypt/hmac.h b/app/jni/gladman-fcrypt/hmac.h new file mode 100644 index 0000000..f84bdcf --- /dev/null +++ b/app/jni/gladman-fcrypt/hmac.h @@ -0,0 +1,81 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This is an implementation of HMAC, the FIPS standard keyed hash function +*/ + +#ifndef _HMAC_H +#define _HMAC_H + +#include + +#include "sha1.h" + +#define IN_BLOCK_LENGTH SHA1_BLOCK_SIZE +#define OUT_BLOCK_LENGTH SHA1_DIGEST_SIZE +#define HMAC_IN_DATA 0xffffffff + +#define HMAC_OK 0 +#define HMAC_BAD_MODE -1 + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef struct +{ unsigned char key[IN_BLOCK_LENGTH]; + sha1_ctx ctx[1]; + unsigned int klen; +} hmac_ctx; + +#ifdef BUILDING_FCRYPT +INTERNAL void hmac_sha1_begin(hmac_ctx cx[1]); + +INTERNAL int hmac_sha1_key(const unsigned char key[], unsigned int key_len, hmac_ctx cx[1]); + +INTERNAL void hmac_sha1_data(const unsigned char data[], unsigned int data_len, hmac_ctx cx[1]); + +INTERNAL void hmac_sha1_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1]); +#endif + +#if 0 /* not used */ +INTERNAL void hmac_sha1(const unsigned char key[], unsigned int key_len, + const unsigned char data[], unsigned int data_len, + unsigned char mac[], unsigned int mac_len); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/app/jni/gladman-fcrypt/pwd2key.c b/app/jni/gladman-fcrypt/pwd2key.c new file mode 100644 index 0000000..3bda272 --- /dev/null +++ b/app/jni/gladman-fcrypt/pwd2key.c @@ -0,0 +1,159 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This is an implementation of RFC2898, which specifies key derivation from + a password and a salt value. +*/ + +#include +#include "hmac.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +INTERNAL void derive_key(const unsigned char pwd[], /* the PASSWORD */ + unsigned int pwd_len, /* and its length */ + const unsigned char salt[], /* the SALT and its */ + unsigned int salt_len, /* length */ + unsigned int iter, /* the number of iterations */ + unsigned char key[], /* space for the output key */ + unsigned int key_len)/* and its required length */ +{ + unsigned int i, j, k, n_blk; + unsigned char uu[OUT_BLOCK_LENGTH], ux[OUT_BLOCK_LENGTH]; + hmac_ctx c1[1], c2[1], c3[1]; + + /* set HMAC context (c1) for password */ + hmac_sha1_begin(c1); + hmac_sha1_key(pwd, pwd_len, c1); + + /* set HMAC context (c2) for password and salt */ + memcpy(c2, c1, sizeof(hmac_ctx)); + hmac_sha1_data(salt, salt_len, c2); + + /* find the number of SHA blocks in the key */ + n_blk = 1 + (key_len - 1) / OUT_BLOCK_LENGTH; + + for(i = 0; i < n_blk; ++i) /* for each block in key */ + { + /* ux[] holds the running xor value */ + memset(ux, 0, OUT_BLOCK_LENGTH); + + /* set HMAC context (c3) for password and salt */ + memcpy(c3, c2, sizeof(hmac_ctx)); + + /* enter additional data for 1st block into uu */ + uu[0] = (unsigned char)((i + 1) >> 24); + uu[1] = (unsigned char)((i + 1) >> 16); + uu[2] = (unsigned char)((i + 1) >> 8); + uu[3] = (unsigned char)(i + 1); + + /* this is the key mixing iteration */ + for(j = 0, k = 4; j < iter; ++j) + { + /* add previous round data to HMAC */ + hmac_sha1_data(uu, k, c3); + + /* obtain HMAC for uu[] */ + hmac_sha1_end(uu, OUT_BLOCK_LENGTH, c3); + + /* xor into the running xor block */ + for(k = 0; k < OUT_BLOCK_LENGTH; ++k) + ux[k] ^= uu[k]; + + /* set HMAC context (c3) for password */ + memcpy(c3, c1, sizeof(hmac_ctx)); + } + + /* compile key blocks into the key output */ + j = 0; k = i * OUT_BLOCK_LENGTH; + while(j < OUT_BLOCK_LENGTH && k < key_len) + key[k++] = ux[j++]; + } +} + +#ifdef TEST + +#include + +struct +{ unsigned int pwd_len; + unsigned int salt_len; + unsigned int it_count; + unsigned char *pwd; + unsigned char salt[32]; + unsigned char key[32]; +} tests[] = +{ + { 8, 4, 5, (unsigned char*)"password", + { 0x12, 0x34, 0x56, 0x78 }, + { 0x5c, 0x75, 0xce, 0xf0, 0x1a, 0x96, 0x0d, 0xf7, + 0x4c, 0xb6, 0xb4, 0x9b, 0x9e, 0x38, 0xe6, 0xb5 } /* ... */ + }, + { 8, 8, 5, (unsigned char*)"password", + { 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 }, + { 0xd1, 0xda, 0xa7, 0x86, 0x15, 0xf2, 0x87, 0xe6, + 0xa1, 0xc8, 0xb1, 0x20, 0xd7, 0x06, 0x2a, 0x49 } /* ... */ + } +}; + +int main() +{ unsigned int i, j, key_len = 256; + unsigned char key[256]; + + printf("\nTest of RFC2898 Password Based Key Derivation"); + for(i = 0; i < 2; ++i) + { + derive_key(tests[i].pwd, tests[i].pwd_len, tests[i].salt, + tests[i].salt_len, tests[i].it_count, key, key_len); + + printf("\ntest %i: ", i + 1); + printf("key %s", memcmp(tests[i].key, key, 16) ? "is bad" : "is good"); + for(j = 0; j < key_len && j < 64; j += 4) + { + if(j % 16 == 0) + printf("\n"); + printf("0x%02x%02x%02x%02x ", key[j], key[j + 1], key[j + 2], key[j + 3]); + } + printf(j < key_len ? " ... \n" : "\n"); + } + printf("\n"); + return 0; +} + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/app/jni/gladman-fcrypt/pwd2key.h b/app/jni/gladman-fcrypt/pwd2key.h new file mode 100644 index 0000000..b00e288 --- /dev/null +++ b/app/jni/gladman-fcrypt/pwd2key.h @@ -0,0 +1,60 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This is an implementation of RFC2898, which specifies key derivation from + a password and a salt value. +*/ + +#ifndef PWD2KEY_H +#define PWD2KEY_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#ifdef BUILDING_FCRYPT +INTERNAL void derive_key( + const unsigned char pwd[], /* the PASSWORD, and */ + unsigned int pwd_len, /* its length */ + const unsigned char salt[], /* the SALT and its */ + unsigned int salt_len, /* length */ + unsigned int iter, /* the number of iterations */ + unsigned char key[], /* space for the output key */ + unsigned int key_len); /* and its required length */ +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/app/jni/gladman-fcrypt/sha1.c b/app/jni/gladman-fcrypt/sha1.c new file mode 100644 index 0000000..4e2c196 --- /dev/null +++ b/app/jni/gladman-fcrypt/sha1.c @@ -0,0 +1,287 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This is a byte oriented version of SHA1 that operates on arrays of bytes + stored in memory. +*/ + +#include /* for memcpy() etc. */ +#include /* for _lrotl with VC++ */ + +#include "sha1.h" + +#if defined(__cplusplus) +extern "C" +{ +#if 0 +} +#endif +#endif + +/* + To obtain the highest speed on processors with 32-bit words, this code + needs to determine the order in which bytes are packed into such words. + The following block of code is an attempt to capture the most obvious + ways in which various environemnts specify their endian definitions. + It may well fail, in which case the definitions will need to be set by + editing at the points marked **** EDIT HERE IF NECESSARY **** below. +*/ +#define SHA_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define SHA_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#include "config.h" + +#if !defined(PLATFORM_BYTE_ORDER) +# if defined(WORDS_BIGENDIAN) +# define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN +# else +# define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN +# endif +#endif + +#if !defined(PLATFORM_BYTE_ORDER) +#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN) +# if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# if defined(BYTE_ORDER) +# if (BYTE_ORDER == LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN +# elif (BYTE_ORDER == BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN +# endif +# endif +# elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN +# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN +# endif +#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN) +# if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# if defined(_BYTE_ORDER) +# if (_BYTE_ORDER == _LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN +# elif (_BYTE_ORDER == _BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN +# endif +# endif +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN +# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN +# endif +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +#define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +#define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN +#elif (('1234' >> 24) == '1') +# define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN +#elif (('4321' >> 24) == '1') +# define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN +#endif +#endif + +#if !defined(PLATFORM_BYTE_ORDER) +# error Please set undetermined byte order (lines 87 or 89 of sha1.c). +#endif + +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) + +#if (PLATFORM_BYTE_ORDER == SHA_BIG_ENDIAN) +#define swap_b32(x) (x) +#elif defined(bswap_32) +#define swap_b32(x) bswap_32(x) +#else +#define swap_b32(x) ((rotl32((x), 8) & 0x00ff00ff) | (rotl32((x), 24) & 0xff00ff00)) +#endif + +#define SHA1_MASK (SHA1_BLOCK_SIZE - 1) + +/* reverse byte order in 32-bit words */ + +#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z))) +#define parity(x,y,z) ((x) ^ (y) ^ (z)) +#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* A normal version as set out in the FIPS */ + +#define rnd(f,k) \ + t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \ + e = d; d = c; c = rotl32(b, 30); b = t + +INTERNAL void sha1_compile(sha1_ctx ctx[1]) +{ sha1_32t w[80], i, a, b, c, d, e, t; + + /* note that words are compiled from the buffer into 32-bit */ + /* words in big-endian order so an order reversal is needed */ + /* here on little endian machines */ + for(i = 0; i < SHA1_BLOCK_SIZE / 4; ++i) + w[i] = swap_b32(ctx->wbuf[i]); + + for(i = SHA1_BLOCK_SIZE / 4; i < 80; ++i) + w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1); + + a = ctx->hash[0]; + b = ctx->hash[1]; + c = ctx->hash[2]; + d = ctx->hash[3]; + e = ctx->hash[4]; + + for(i = 0; i < 20; ++i) + { + rnd(ch, 0x5a827999); + } + + for(i = 20; i < 40; ++i) + { + rnd(parity, 0x6ed9eba1); + } + + for(i = 40; i < 60; ++i) + { + rnd(maj, 0x8f1bbcdc); + } + + for(i = 60; i < 80; ++i) + { + rnd(parity, 0xca62c1d6); + } + + ctx->hash[0] += a; + ctx->hash[1] += b; + ctx->hash[2] += c; + ctx->hash[3] += d; + ctx->hash[4] += e; +} + +INTERNAL void sha1_begin(sha1_ctx ctx[1]) +{ + ctx->count[0] = ctx->count[1] = 0; + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; + ctx->hash[4] = 0xc3d2e1f0; +} + +/* SHA1 hash data in an array of bytes into hash buffer and */ +/* call the hash_compile function as required. */ + +INTERNAL void sha1_hash(const unsigned char data[], unsigned int len, sha1_ctx ctx[1]) +{ sha1_32t pos = (sha1_32t)(ctx->count[0] & SHA1_MASK), + space = SHA1_BLOCK_SIZE - pos; + const unsigned char *sp = data; + + if((ctx->count[0] += len) < len) + ++(ctx->count[1]); + + while(len >= space) /* tranfer whole blocks if possible */ + { + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space); + sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0; + sha1_compile(ctx); + } + + /*lint -e{803} conceivable data overrun */ + /* there are two cases: the above while loop entered or not */ + /* entered. If not entered, 'space = SHA1_BLOCK_SIZE - pos' */ + /* and 'len < space' so that 'len + pos < SHA1_BLOCK_SIZE'. */ + /* If entered, 'pos = 0', 'space = SHA1_BLOCK_SIZE' and */ + /* 'len < space' so that 'pos + len < SHA1_BLOCK_SIZE'. In */ + /* both cases, therefore, the memory copy is in the buffer */ + + memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len); +} + +/* SHA1 final padding and digest calculation */ + +#if (PLATFORM_BYTE_ORDER == SHA_LITTLE_ENDIAN) +static sha1_32t mask[4] = + { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff }; +static sha1_32t bits[4] = + { 0x00000080, 0x00008000, 0x00800000, 0x80000000 }; +#else +static sha1_32t mask[4] = + { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 }; +static sha1_32t bits[4] = + { 0x80000000, 0x00800000, 0x00008000, 0x00000080 }; +#endif + +INTERNAL void sha1_end(unsigned char hval[], sha1_ctx ctx[1]) +{ sha1_32t i = (sha1_32t)(ctx->count[0] & SHA1_MASK); + + /* mask out the rest of any partial 32-bit word and then set */ + /* the next byte to 0x80. On big-endian machines any bytes in */ + /* the buffer will be at the top end of 32 bit words, on little */ + /* endian machines they will be at the bottom. Hence the AND */ + /* and OR masks above are reversed for little endian systems */ + /* Note that we can always add the first padding byte at this */ + /* point because the buffer always has at least one empty slot */ + ctx->wbuf[i >> 2] = (ctx->wbuf[i >> 2] & mask[i & 3]) | bits[i & 3]; + + /* we need 9 or more empty positions, one for the padding byte */ + /* (above) and eight for the length count. If there is not */ + /* enough space pad and empty the buffer */ + if(i > SHA1_BLOCK_SIZE - 9) + { + if(i < 60) ctx->wbuf[15] = 0; + sha1_compile(ctx); + i = 0; + } + else /* compute a word index for the empty buffer positions */ + i = (i >> 2) + 1; + + while(i < 14) /* and zero pad all but last two positions */ + ctx->wbuf[i++] = 0; + + /* assemble the eight byte counter in in big-endian format */ + ctx->wbuf[14] = swap_b32((ctx->count[1] << 3) | (ctx->count[0] >> 29)); + ctx->wbuf[15] = swap_b32(ctx->count[0] << 3); + + sha1_compile(ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* misaligned for 32-bit words */ + /*lint -e{504} unusual shift operation (unusually formed right argument) */ + for(i = 0; i < SHA1_DIGEST_SIZE; ++i) + hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3))); +} + +#if 0 /* not used */ +INTERNAL void sha1(unsigned char hval[], const unsigned char data[], unsigned int len) +{ sha1_ctx cx[1]; + + sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx); +} +#endif + +#if defined(__cplusplus) +} +#endif diff --git a/app/jni/gladman-fcrypt/sha1.h b/app/jni/gladman-fcrypt/sha1.h new file mode 100644 index 0000000..58529d4 --- /dev/null +++ b/app/jni/gladman-fcrypt/sha1.h @@ -0,0 +1,79 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 24/01/2003 + + This file contains the definitions needed for SHA1 +*/ + +#ifndef _SHA1_H +#define _SHA1_H + +#include + +#define SHA1_BLOCK_SIZE 64 +#define SHA1_DIGEST_SIZE 20 + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* define an unsigned 32-bit type */ + +#include "config.h" + +typedef zip_uint32_t sha1_32t; + +/* type to hold the SHA256 context */ + +typedef struct +{ sha1_32t count[2]; + sha1_32t hash[5]; + sha1_32t wbuf[16]; +} sha1_ctx; + +#ifdef BUILDING_FCRYPT +INTERNAL void sha1_compile(sha1_ctx ctx[1]); + +INTERNAL void sha1_begin(sha1_ctx ctx[1]); +INTERNAL void sha1_hash(const unsigned char data[], unsigned int len, sha1_ctx ctx[1]); +INTERNAL void sha1_end(unsigned char hval[], sha1_ctx ctx[1]); +#endif + +#if 0 /* not used */ +INTERNAL void sha1(unsigned char hval[], const unsigned char data[], unsigned int len); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/app/jni/io_github_xausky_bh3modmanager_FusionZip.c b/app/jni/io_github_xausky_bh3modmanager_FusionZip.c new file mode 100644 index 0000000..ca83fe4 --- /dev/null +++ b/app/jni/io_github_xausky_bh3modmanager_FusionZip.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +#ifdef __ANDROID_NDK__ +#include +#include "zip.h" +#include "io_github_xausky_bh3modmanager_FusionZip.h" +#else +#include +#endif + +#ifdef __ANDROID_NDK__ +#define __FUSION_LOG(str, args...) __android_log_print(ANDROID_LOG_DEBUG, "BH3ModManager", str, ##args) +#else +#define __FUSION_LOG(str, args...) printf(str, ##args) +#endif + +#define BACKUP_BUFFER_ZISE (10240) + +int fusionZip(const char * backupDirPath, const char * fusionDirPath, const char * prefixString, zip_t* target_zip){ + DIR* dir = opendir(fusionDirPath); + if(dir == NULL) + { + __FUSION_LOG("fusionDir open failed, error: %s, path: %s\n", strerror(errno), fusionDirPath); + return -1; + } + ZIP_ER_EXISTS; + struct dirent* dirent; + char archive_path_buffer[1024]; + char source_path_buffer[1024]; + char backup_path_buffer[1024]; + void* backup_buffer[BACKUP_BUFFER_ZISE]; + zip_error_t error; + while((dirent = readdir(dir)) != NULL){ + if(dirent->d_type != DT_REG){ + continue; + } + sprintf(archive_path_buffer, "%s/%s", prefixString, dirent->d_name); + sprintf(source_path_buffer, "%s/%s", fusionDirPath, dirent->d_name); + zip_source_t * source = zip_source_file_create(source_path_buffer, 0, 0, &error); + if(source == NULL){ + __FUSION_LOG("zip source file create failed, error: %s, path: %s\n", strerror(errno), source_path_buffer); + closedir(dir); + return -1; + } + zip_int64_t idx = 0; + if ((idx = zip_name_locate(target_zip, archive_path_buffer, ZIP_FL_ENC_GUESS)) >= 0) { + if(backupDirPath != NULL){ + sprintf(backup_path_buffer, "%s/%s", backupDirPath, dirent->d_name); + int backup_file = open(backup_path_buffer, O_CREAT|O_WRONLY|O_EXCL, 0600); + if(backup_file != -1){ + zip_file_t* file = zip_fopen_index(target_zip, idx, ZIP_FL_UNCHANGED); + if(file == NULL){ + __FUSION_LOG("backup zip file open failed, error: %s, backup path: %s, archive path: %s\n", zip_strerror(target_zip), backup_path_buffer, archive_path_buffer); + closedir(dir); + zip_source_close(source); + close(backup_file); + return -1; + } + int len = 0; + while((len = zip_fread(file, backup_buffer, BACKUP_BUFFER_ZISE)) > 0){ + write(backup_file, backup_buffer, len); + } + if(len == -1){ + __FUSION_LOG("backup zip file read failed, error: %s, backup path: %s, archive path: %s\n", zip_strerror(target_zip), backup_path_buffer, archive_path_buffer); + zip_fclose(file); + closedir(dir); + zip_source_close(source); + close(backup_file); + return -1; + } + zip_fclose(file); + close(backup_file); + } else { + int error = errno; + if(error != EEXIST){ + __FUSION_LOG("backup file open failed, error: %s, backup path: %s, archive path: %s\n", strerror(error), backup_path_buffer, archive_path_buffer); + closedir(dir); + zip_source_close(source); + return -1; + } + } + } + if(zip_file_replace(target_zip, (zip_uint64_t)idx, source, ZIP_FL_OVERWRITE) == -1){ + __FUSION_LOG("zip file add failed, error: %s, source path: %s, archive path: %s\n", zip_strerror(target_zip), source_path_buffer, archive_path_buffer); + closedir(dir); + zip_source_close(source); + return -1; + } + __FUSION_LOG("zip file replace ok, %s -> %s\n", source_path_buffer, archive_path_buffer); + } + } + closedir(dir); + return 0; +} + +int patchZip(const char * backupDirPath, const char * fusionDirPath, const char * prefixString, const char * targetPath){ + int enumber = 0; + zip_t* zip = zip_open(targetPath, 0, &enumber); + if(zip == NULL){ + zip_error_t error; + zip_error_init_with_code(&error, enumber); + __FUSION_LOG("dest zip open failed, error: %s, path: %s\n", zip_error_strerror(&error), targetPath); + zip_error_fini(&error); + return -1; + } + if(fusionZip(NULL, backupDirPath, prefixString, zip) == -1){ + __FUSION_LOG("patch backup, error: %s, path: %s\n", zip_strerror(zip), targetPath); + zip_close(zip); + return -1; + } + if(fusionZip(backupDirPath,fusionDirPath , prefixString, zip) == -1){ + __FUSION_LOG("patch fusion, error: %s, path: %s\n", zip_strerror(zip), targetPath); + zip_close(zip); + return -1; + } + zip_close(zip); + return 0; +} + +#ifdef __ANDROID_NDK__ +JNIEXPORT jint JNICALL Java_io_github_xausky_bh3modmanager_FusionZip_patchZip + (JNIEnv *env, jclass cls, jstring backupDir, jstring fusionDir, jstring prefix, jstring target) { + const char * backupDirPath = (*env)->GetStringUTFChars(env, backupDir,JNI_FALSE); + const char * fusionDirPath = (*env)->GetStringUTFChars(env, fusionDir,JNI_FALSE); + const char * prefixString = (*env)->GetStringUTFChars(env, prefix,JNI_FALSE); + const char * targetPath = (*env)->GetStringUTFChars(env, target,JNI_FALSE); + return patchZip(backupDirPath, fusionDirPath, prefixString, targetPath); +} +#else +int main(int argc, char* argv[]){ + if(patchZip(argv[1], argv[2], argv[3], argv[4]) != 0){ + __FUSION_LOG("patch zip error\n"); + return -1; + } + return 0; +} +#endif \ No newline at end of file diff --git a/app/jni/io_github_xausky_bh3modmanager_FusionZip.h b/app/jni/io_github_xausky_bh3modmanager_FusionZip.h new file mode 100644 index 0000000..d3f6898 --- /dev/null +++ b/app/jni/io_github_xausky_bh3modmanager_FusionZip.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class io_github_xausky_bh3modmanager_FusionZip */ + +#ifndef _Included_io_github_xausky_bh3modmanager_FusionZip +#define _Included_io_github_xausky_bh3modmanager_FusionZip +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: io_github_xausky_bh3modmanager_FusionZip + * Method: patchZip + * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT jint JNICALL Java_io_github_xausky_bh3modmanager_FusionZip_patchZip + (JNIEnv *, jclass, jstring, jstring, jstring, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/app/jni/mkstemp.c b/app/jni/mkstemp.c new file mode 100644 index 0000000..cdfc0e2 --- /dev/null +++ b/app/jni/mkstemp.c @@ -0,0 +1,153 @@ +/* Adapted from NetBSB libc by Dieter Baron */ + +/* NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#endif +#include +#include + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + + +int +_zip_mkstemp(char *path) +{ +#ifdef _WIN32 + int ret; + ret = _creat(_mktemp(path), _S_IREAD|_S_IWRITE); + if (ret == -1) { + return 0; + } else { + return ret; + } +#else + int fd; + char *start, *trv; + struct stat sbuf; + pid_t pid; + + /* To guarantee multiple calls generate unique names even if + the file is not created. 676 different possibilities with 7 + or more X's, 26 with 6 or less. */ + static char xtra[2] = "aa"; + int xcnt = 0; + + pid = getpid(); + + /* Move to end of path and count trailing X's. */ + for (trv = path; *trv; ++trv) + if (*trv == 'X') + xcnt++; + else + xcnt = 0; + + /* Use at least one from xtra. Use 2 if more than 6 X's. */ + if (*(trv - 1) == 'X') + *--trv = xtra[0]; + if (xcnt > 6 && *(trv - 1) == 'X') + *--trv = xtra[1]; + + /* Set remaining X's to pid digits with 0's to the left. */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* update xtra for next call. */ + if (xtra[0] != 'z') + xtra[0]++; + else { + xtra[0] = 'a'; + if (xtra[1] != 'z') + xtra[1]++; + else + xtra[1] = 'a'; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return (0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return (0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if ((fd=open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0) + return (fd); + if (errno != EEXIST) + return (0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return (0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit((unsigned char)*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +#endif +} diff --git a/app/jni/zip.h b/app/jni/zip.h new file mode 100644 index 0000000..ff37ed3 --- /dev/null +++ b/app/jni/zip.h @@ -0,0 +1,446 @@ +#ifndef _HAD_ZIP_H +#define _HAD_ZIP_H + +/* + zip.h -- exported declarations. + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* fix autoindent */ +#endif +#endif + +#include + +#ifndef ZIP_EXTERN +# ifndef ZIP_STATIC +# ifdef _WIN32 +# define ZIP_EXTERN __declspec(dllimport) +# elif defined(__GNUC__) && __GNUC__ >= 4 +# define ZIP_EXTERN __attribute__ ((visibility ("default"))) +# else +# define ZIP_EXTERN +# endif +# else +# define ZIP_EXTERN +# endif +#endif + +#include +#include +#include + +/* flags for zip_open */ + +#define ZIP_CREATE 1 +#define ZIP_EXCL 2 +#define ZIP_CHECKCONS 4 +#define ZIP_TRUNCATE 8 +#define ZIP_RDONLY 16 + + +/* flags for zip_name_locate, zip_fopen, zip_stat, ... */ + +#define ZIP_FL_NOCASE 1u /* ignore case on name lookup */ +#define ZIP_FL_NODIR 2u /* ignore directory component */ +#define ZIP_FL_COMPRESSED 4u /* read compressed data */ +#define ZIP_FL_UNCHANGED 8u /* use original data, ignoring changes */ +#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */ +#define ZIP_FL_ENCRYPTED 32u /* read encrypted data (implies ZIP_FL_COMPRESSED) */ +#define ZIP_FL_ENC_GUESS 0u /* guess string encoding (is default) */ +#define ZIP_FL_ENC_RAW 64u /* get unmodified string */ +#define ZIP_FL_ENC_STRICT 128u /* follow specification strictly */ +#define ZIP_FL_LOCAL 256u /* in local header */ +#define ZIP_FL_CENTRAL 512u /* in central directory */ +/* 1024u reserved for internal use */ +#define ZIP_FL_ENC_UTF_8 2048u /* string is UTF-8 encoded */ +#define ZIP_FL_ENC_CP437 4096u /* string is CP437 encoded */ +#define ZIP_FL_OVERWRITE 8192u /* zip_file_add: if file with name exists, overwrite (replace) it */ + +/* archive global flags flags */ + +#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */ + + +/* create a new extra field */ + +#define ZIP_EXTRA_FIELD_ALL ZIP_UINT16_MAX +#define ZIP_EXTRA_FIELD_NEW ZIP_UINT16_MAX + + +/* libzip error codes */ + +#define ZIP_ER_OK 0 /* N No error */ +#define ZIP_ER_MULTIDISK 1 /* N Multi-disk zip archives not supported */ +#define ZIP_ER_RENAME 2 /* S Renaming temporary file failed */ +#define ZIP_ER_CLOSE 3 /* S Closing zip archive failed */ +#define ZIP_ER_SEEK 4 /* S Seek error */ +#define ZIP_ER_READ 5 /* S Read error */ +#define ZIP_ER_WRITE 6 /* S Write error */ +#define ZIP_ER_CRC 7 /* N CRC error */ +#define ZIP_ER_ZIPCLOSED 8 /* N Containing zip archive was closed */ +#define ZIP_ER_NOENT 9 /* N No such file */ +#define ZIP_ER_EXISTS 10 /* N File already exists */ +#define ZIP_ER_OPEN 11 /* S Can't open file */ +#define ZIP_ER_TMPOPEN 12 /* S Failure to create temporary file */ +#define ZIP_ER_ZLIB 13 /* Z Zlib error */ +#define ZIP_ER_MEMORY 14 /* N Malloc failure */ +#define ZIP_ER_CHANGED 15 /* N Entry has been changed */ +#define ZIP_ER_COMPNOTSUPP 16 /* N Compression method not supported */ +#define ZIP_ER_EOF 17 /* N Premature end of file */ +#define ZIP_ER_INVAL 18 /* N Invalid argument */ +#define ZIP_ER_NOZIP 19 /* N Not a zip archive */ +#define ZIP_ER_INTERNAL 20 /* N Internal error */ +#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */ +#define ZIP_ER_REMOVE 22 /* S Can't remove file */ +#define ZIP_ER_DELETED 23 /* N Entry has been deleted */ +#define ZIP_ER_ENCRNOTSUPP 24 /* N Encryption method not supported */ +#define ZIP_ER_RDONLY 25 /* N Read-only archive */ +#define ZIP_ER_NOPASSWD 26 /* N No password provided */ +#define ZIP_ER_WRONGPASSWD 27 /* N Wrong password provided */ +#define ZIP_ER_OPNOTSUPP 28 /* N Operation not supported */ +#define ZIP_ER_INUSE 29 /* N Resource still in use */ +#define ZIP_ER_TELL 30 /* S Tell error */ +#define ZIP_ER_COMPRESSED_DATA 31 /* N Compressed data invalid */ + +/* type of system error value */ + +#define ZIP_ET_NONE 0 /* sys_err unused */ +#define ZIP_ET_SYS 1 /* sys_err is errno */ +#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */ + +/* compression methods */ + +#define ZIP_CM_DEFAULT -1 /* better of deflate or store */ +#define ZIP_CM_STORE 0 /* stored (uncompressed) */ +#define ZIP_CM_SHRINK 1 /* shrunk */ +#define ZIP_CM_REDUCE_1 2 /* reduced with factor 1 */ +#define ZIP_CM_REDUCE_2 3 /* reduced with factor 2 */ +#define ZIP_CM_REDUCE_3 4 /* reduced with factor 3 */ +#define ZIP_CM_REDUCE_4 5 /* reduced with factor 4 */ +#define ZIP_CM_IMPLODE 6 /* imploded */ +/* 7 - Reserved for Tokenizing compression algorithm */ +#define ZIP_CM_DEFLATE 8 /* deflated */ +#define ZIP_CM_DEFLATE64 9 /* deflate64 */ +#define ZIP_CM_PKWARE_IMPLODE 10 /* PKWARE imploding */ +/* 11 - Reserved by PKWARE */ +#define ZIP_CM_BZIP2 12 /* compressed using BZIP2 algorithm */ +/* 13 - Reserved by PKWARE */ +#define ZIP_CM_LZMA 14 /* LZMA (EFS) */ +/* 15-17 - Reserved by PKWARE */ +#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */ +#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */ +#define ZIP_CM_XZ 95 /* XZ compressed data */ +#define ZIP_CM_JPEG 96 /* Compressed Jpeg data */ +#define ZIP_CM_WAVPACK 97 /* WavPack compressed data */ +#define ZIP_CM_PPMD 98 /* PPMd version I, Rev 1 */ + +/* encryption methods */ + +#define ZIP_EM_NONE 0 /* not encrypted */ +#define ZIP_EM_TRAD_PKWARE 1 /* traditional PKWARE encryption */ +#if 0 /* Strong Encryption Header not parsed yet */ +#define ZIP_EM_DES 0x6601 /* strong encryption: DES */ +#define ZIP_EM_RC2_OLD 0x6602 /* strong encryption: RC2, version < 5.2 */ +#define ZIP_EM_3DES_168 0x6603 +#define ZIP_EM_3DES_112 0x6609 +#define ZIP_EM_PKZIP_AES_128 0x660e +#define ZIP_EM_PKZIP_AES_192 0x660f +#define ZIP_EM_PKZIP_AES_256 0x6610 +#define ZIP_EM_RC2 0x6702 /* strong encryption: RC2, version >= 5.2 */ +#define ZIP_EM_RC4 0x6801 +#endif +#define ZIP_EM_AES_128 0x0101 /* Winzip AES encryption */ +#define ZIP_EM_AES_192 0x0102 +#define ZIP_EM_AES_256 0x0103 +#define ZIP_EM_UNKNOWN 0xffff /* unknown algorithm */ + +#define ZIP_OPSYS_DOS 0x00u +#define ZIP_OPSYS_AMIGA 0x01u +#define ZIP_OPSYS_OPENVMS 0x02u +#define ZIP_OPSYS_UNIX 0x03u +#define ZIP_OPSYS_VM_CMS 0x04u +#define ZIP_OPSYS_ATARI_ST 0x05u +#define ZIP_OPSYS_OS_2 0x06u +#define ZIP_OPSYS_MACINTOSH 0x07u +#define ZIP_OPSYS_Z_SYSTEM 0x08u +#define ZIP_OPSYS_CPM 0x09u +#define ZIP_OPSYS_WINDOWS_NTFS 0x0au +#define ZIP_OPSYS_MVS 0x0bu +#define ZIP_OPSYS_VSE 0x0cu +#define ZIP_OPSYS_ACORN_RISC 0x0du +#define ZIP_OPSYS_VFAT 0x0eu +#define ZIP_OPSYS_ALTERNATE_MVS 0x0fu +#define ZIP_OPSYS_BEOS 0x10u +#define ZIP_OPSYS_TANDEM 0x11u +#define ZIP_OPSYS_OS_400 0x12u +#define ZIP_OPSYS_OS_X 0x13u + +#define ZIP_OPSYS_DEFAULT ZIP_OPSYS_UNIX + + +enum zip_source_cmd { + ZIP_SOURCE_OPEN, /* prepare for reading */ + ZIP_SOURCE_READ, /* read data */ + ZIP_SOURCE_CLOSE, /* reading is done */ + ZIP_SOURCE_STAT, /* get meta information */ + ZIP_SOURCE_ERROR, /* get error information */ + ZIP_SOURCE_FREE, /* cleanup and free resources */ + ZIP_SOURCE_SEEK, /* set position for reading */ + ZIP_SOURCE_TELL, /* get read position */ + ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */ + ZIP_SOURCE_COMMIT_WRITE, /* writing is done */ + ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */ + ZIP_SOURCE_WRITE, /* write data */ + ZIP_SOURCE_SEEK_WRITE, /* set position for writing */ + ZIP_SOURCE_TELL_WRITE, /* get write position */ + ZIP_SOURCE_SUPPORTS, /* check whether source supports command */ + ZIP_SOURCE_REMOVE, /* remove file */ + ZIP_SOURCE_GET_COMPRESSION_FLAGS, /* get compression flags, internal only */ + ZIP_SOURCE_BEGIN_WRITE_CLONING /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */ +}; +typedef enum zip_source_cmd zip_source_cmd_t; + +#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1)<<(cmd)) + +#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_CLOSE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_STAT) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ERROR) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_FREE)) + +#define ZIP_SOURCE_SUPPORTS_SEEKABLE (ZIP_SOURCE_SUPPORTS_READABLE \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SUPPORTS)) + +#define ZIP_SOURCE_SUPPORTS_WRITABLE (ZIP_SOURCE_SUPPORTS_SEEKABLE \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_COMMIT_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ROLLBACK_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE)) + +/* for use by sources */ +struct zip_source_args_seek { + zip_int64_t offset; + int whence; +}; + +typedef struct zip_source_args_seek zip_source_args_seek_t; +#define ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), (type *)NULL : (type *)(data)) + + +/* error information */ +/* use zip_error_*() to access */ +struct zip_error { + int zip_err; /* libzip error code (ZIP_ER_*) */ + int sys_err; /* copy of errno (E*) or zlib error code */ + char *str; /* string representation or NULL */ +}; + +#define ZIP_STAT_NAME 0x0001u +#define ZIP_STAT_INDEX 0x0002u +#define ZIP_STAT_SIZE 0x0004u +#define ZIP_STAT_COMP_SIZE 0x0008u +#define ZIP_STAT_MTIME 0x0010u +#define ZIP_STAT_CRC 0x0020u +#define ZIP_STAT_COMP_METHOD 0x0040u +#define ZIP_STAT_ENCRYPTION_METHOD 0x0080u +#define ZIP_STAT_FLAGS 0x0100u + +struct zip_stat { + zip_uint64_t valid; /* which fields have valid values */ + const char *name; /* name of the file */ + zip_uint64_t index; /* index within archive */ + zip_uint64_t size; /* size of file (uncompressed) */ + zip_uint64_t comp_size; /* size of file (compressed) */ + time_t mtime; /* modification time */ + zip_uint32_t crc; /* crc of file data */ + zip_uint16_t comp_method; /* compression method used */ + zip_uint16_t encryption_method; /* encryption method used */ + zip_uint32_t flags; /* reserved for future use */ +}; + +struct zip_buffer_fragment { + zip_uint8_t *data; + zip_uint64_t length; +}; + +struct zip; +struct zip_file; +struct zip_source; + +typedef struct zip zip_t; +typedef struct zip_error zip_error_t; +typedef struct zip_file zip_file_t; +typedef struct zip_source zip_source_t; +typedef struct zip_stat zip_stat_t; +typedef struct zip_buffer_fragment zip_buffer_fragment_t; + +typedef zip_uint32_t zip_flags_t; + +typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t); +typedef void (*zip_progress_callback)(zip_t *, double, void *); + +#ifndef ZIP_DISABLE_DEPRECATED +typedef void (*zip_progress_callback_t)(double); +ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t); /* use zip_register_progress_callback_with_state */ + +ZIP_EXTERN zip_int64_t zip_add(zip_t *, const char *, zip_source_t *); /* use zip_file_add */ +ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *, const char *); /* use zip_dir_add */ +ZIP_EXTERN const char *zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */ +ZIP_EXTERN int zip_get_num_files(zip_t *); /* use zip_get_num_entries instead */ +ZIP_EXTERN int zip_rename(zip_t *, zip_uint64_t, const char *); /* use zip_file_rename */ +ZIP_EXTERN int zip_replace(zip_t *, zip_uint64_t, zip_source_t *); /* use zip_file_replace */ +ZIP_EXTERN int zip_set_file_comment(zip_t *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */ +ZIP_EXTERN int zip_error_get_sys_type(int); /* use zip_error_system_type */ +ZIP_EXTERN void zip_error_get(zip_t *, int *, int *); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */ +ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int); /* use zip_error_init_with_code / zip_error_strerror */ +ZIP_EXTERN void zip_file_error_get(zip_file_t *, int *, int *); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */ +#endif + +ZIP_EXTERN int zip_close(zip_t *); +ZIP_EXTERN int zip_delete(zip_t *, zip_uint64_t); +ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *, const char *, zip_flags_t); +ZIP_EXTERN void zip_discard(zip_t *); + +ZIP_EXTERN zip_error_t *zip_get_error(zip_t *); +ZIP_EXTERN void zip_error_clear(zip_t *); +ZIP_EXTERN int zip_error_code_zip(const zip_error_t *); +ZIP_EXTERN int zip_error_code_system(const zip_error_t *); +ZIP_EXTERN void zip_error_fini(zip_error_t *); +ZIP_EXTERN void zip_error_init(zip_error_t *); +ZIP_EXTERN void zip_error_init_with_code(zip_error_t *, int); +ZIP_EXTERN void zip_error_set(zip_error_t *, int, int); +ZIP_EXTERN const char *zip_error_strerror(zip_error_t *); +ZIP_EXTERN int zip_error_system_type(const zip_error_t *); +ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t); + +ZIP_EXTERN int zip_fclose(zip_file_t *); +ZIP_EXTERN zip_t *zip_fdopen(int, int, int *); +ZIP_EXTERN zip_int64_t zip_file_add(zip_t *, const char *, zip_source_t *, unsigned int); +ZIP_EXTERN void zip_file_error_clear(zip_file_t *); +ZIP_EXTERN int zip_file_extra_field_delete(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_set(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t); +ZIP_EXTERN const char *zip_file_get_comment(zip_t *, zip_uint64_t, zip_uint32_t *, zip_flags_t); +ZIP_EXTERN zip_error_t *zip_file_get_error(zip_file_t *); +ZIP_EXTERN int zip_file_get_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t *, zip_uint32_t *); +ZIP_EXTERN int zip_file_rename(zip_t *, zip_uint64_t, const char *, zip_flags_t); +ZIP_EXTERN int zip_file_replace(zip_t *, zip_uint64_t, zip_source_t *, zip_flags_t); +ZIP_EXTERN int zip_file_set_comment(zip_t *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_set_encryption(zip_t *, zip_uint64_t, zip_uint16_t, const char *); +ZIP_EXTERN int zip_file_set_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t); +ZIP_EXTERN int zip_file_set_mtime(zip_t *, zip_uint64_t, time_t, zip_flags_t); +ZIP_EXTERN const char *zip_file_strerror(zip_file_t *); +ZIP_EXTERN zip_file_t *zip_fopen(zip_t *, const char *, zip_flags_t); +ZIP_EXTERN zip_file_t *zip_fopen_encrypted(zip_t *, const char *, zip_flags_t, const char *); +ZIP_EXTERN zip_file_t *zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_file_t *zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *); +ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *, void *, zip_uint64_t); +ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *, zip_int64_t, int); +ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *); +ZIP_EXTERN const char *zip_get_archive_comment(zip_t *, int *, zip_flags_t); +ZIP_EXTERN int zip_get_archive_flag(zip_t *, zip_flags_t, zip_flags_t); +ZIP_EXTERN const char *zip_get_name(zip_t *, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t); +ZIP_EXTERN const char *zip_libzip_version(void); +ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t); +ZIP_EXTERN zip_t *zip_open(const char *, int, int *); +ZIP_EXTERN zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *); +ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *); +ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t); +ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int); +ZIP_EXTERN int zip_set_default_password(zip_t *, const char *); +ZIP_EXTERN int zip_set_file_compression(zip_t *, zip_uint64_t, zip_int32_t, zip_uint32_t); +ZIP_EXTERN int zip_source_begin_write(zip_source_t *); +ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *, zip_uint64_t); +ZIP_EXTERN zip_source_t *zip_source_buffer(zip_t *, const void *, zip_uint64_t, int); +ZIP_EXTERN zip_source_t *zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *); +ZIP_EXTERN zip_source_t *zip_source_buffer_fragment(zip_t *, const zip_buffer_fragment_t *, zip_uint64_t, int); +ZIP_EXTERN zip_source_t *zip_source_buffer_fragment_create(const zip_buffer_fragment_t *, zip_uint64_t, int, zip_error_t *); +ZIP_EXTERN int zip_source_close(zip_source_t *); +ZIP_EXTERN int zip_source_commit_write(zip_source_t *); +ZIP_EXTERN zip_error_t *zip_source_error(zip_source_t *); +ZIP_EXTERN zip_source_t *zip_source_file(zip_t *, const char *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *); +ZIP_EXTERN zip_source_t *zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *); +ZIP_EXTERN void zip_source_free(zip_source_t *); +ZIP_EXTERN zip_source_t *zip_source_function(zip_t *, zip_source_callback, void *); +ZIP_EXTERN zip_source_t *zip_source_function_create(zip_source_callback, void *, zip_error_t *); +ZIP_EXTERN int zip_source_is_deleted(zip_source_t *); +ZIP_EXTERN void zip_source_keep(zip_source_t *); +ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...); +ZIP_EXTERN int zip_source_open(zip_source_t *); +ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *, void *, zip_uint64_t); +ZIP_EXTERN void zip_source_rollback_write(zip_source_t *); +ZIP_EXTERN int zip_source_seek(zip_source_t *, zip_int64_t, int); +ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *, zip_uint64_t, zip_error_t *); +ZIP_EXTERN int zip_source_seek_write(zip_source_t *, zip_int64_t, int); +ZIP_EXTERN int zip_source_stat(zip_source_t *, zip_stat_t *); +ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *); +ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *); +#ifdef _WIN32 +ZIP_EXTERN zip_source_t *zip_source_win32a(zip_t *, const char *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *zip_source_win32a_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *); +ZIP_EXTERN zip_source_t *zip_source_win32handle(zip_t *, void *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip_int64_t, zip_error_t *); +ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *); +#endif +ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *, const void *, zip_uint64_t); +ZIP_EXTERN zip_source_t *zip_source_zip(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t); +ZIP_EXTERN int zip_stat(zip_t *, const char *, zip_flags_t, zip_stat_t *); +ZIP_EXTERN int zip_stat_index(zip_t *, zip_uint64_t, zip_flags_t, zip_stat_t *); +ZIP_EXTERN void zip_stat_init(zip_stat_t *); +ZIP_EXTERN const char *zip_strerror(zip_t *); +ZIP_EXTERN int zip_unchange(zip_t *, zip_uint64_t); +ZIP_EXTERN int zip_unchange_all(zip_t *); +ZIP_EXTERN int zip_unchange_archive(zip_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _HAD_ZIP_H */ diff --git a/app/jni/zip_add.c b/app/jni/zip_add.c new file mode 100644 index 0000000..d1be133 --- /dev/null +++ b/app/jni/zip_add.c @@ -0,0 +1,50 @@ +/* + zip_add.c -- add file via callback function + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +/* + NOTE: Return type is signed so we can return -1 on error. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. +*/ + +ZIP_EXTERN zip_int64_t +zip_add(zip_t *za, const char *name, zip_source_t *source) +{ + return zip_file_add(za, name, source, 0); +} diff --git a/app/jni/zip_add_dir.c b/app/jni/zip_add_dir.c new file mode 100644 index 0000000..14bdeda --- /dev/null +++ b/app/jni/zip_add_dir.c @@ -0,0 +1,45 @@ +/* + zip_add_dir.c -- add directory + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +ZIP_EXTERN zip_int64_t +zip_add_dir(zip_t *za, const char *name) +{ + return zip_dir_add(za, name, 0); +} diff --git a/app/jni/zip_add_entry.c b/app/jni/zip_add_entry.c new file mode 100644 index 0000000..f6212f1 --- /dev/null +++ b/app/jni/zip_add_entry.c @@ -0,0 +1,81 @@ +/* + zip_add_entry.c -- create and init struct zip_entry + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +zip_int64_t +_zip_add_entry(zip_t *za) +{ + zip_uint64_t idx; + + if (za->nentry+1 >= za->nentry_alloc) { + zip_entry_t *rentries; + zip_uint64_t nalloc = za->nentry_alloc; + zip_uint64_t additional_entries = 2 * nalloc; + zip_uint64_t realloc_size; + + if (additional_entries < 16) { + additional_entries = 16; + } + else if (additional_entries > 1024) { + additional_entries = 1024; + } + /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */ + nalloc += additional_entries; + realloc_size = sizeof(struct zip_entry) * (size_t)nalloc; + + if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc); + if (!rentries) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + za->entry = rentries; + za->nentry_alloc = nalloc; + } + + idx = za->nentry++; + + _zip_entry_init(za->entry+idx); + + return (zip_int64_t)idx; +} diff --git a/app/jni/zip_algorithm_bzip2.c b/app/jni/zip_algorithm_bzip2.c new file mode 100644 index 0000000..1748fd4 --- /dev/null +++ b/app/jni/zip_algorithm_bzip2.c @@ -0,0 +1,275 @@ +/* + zip_algorithm_bzip2.c -- bzip2 (de)compression routines + Copyright (C) 2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#if defined(HAVE_LIBBZ2) + +#include +#include +#include + +struct ctx { + zip_error_t *error; + bool compress; + int compression_flags; + bool end_of_input; + bz_stream zstr; +}; + + +static void * +allocate(bool compress, int compression_flags, zip_error_t *error) { + struct ctx *ctx; + + if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + + ctx->error = error; + ctx->compress = compress; + ctx->compression_flags = compression_flags; + if (ctx->compression_flags < 1 || ctx->compression_flags > 9) { + ctx->compression_flags = 9; + } + ctx->end_of_input = false; + + ctx->zstr.bzalloc = NULL; + ctx->zstr.bzfree = NULL; + ctx->zstr.opaque = NULL; + + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(true, compression_flags, error); +} + + +static void * +decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(false, compression_flags, error); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + free(ctx); +} + + +static int +compression_flags(void *ud) { + return 0; +} + + +static int +map_error(int ret) { + switch (ret) { + case BZ_FINISH_OK: + case BZ_FLUSH_OK: + case BZ_OK: + case BZ_RUN_OK: + case BZ_STREAM_END: + return ZIP_ER_OK; + + case BZ_DATA_ERROR: + case BZ_DATA_ERROR_MAGIC: + case BZ_UNEXPECTED_EOF: + return ZIP_ER_COMPRESSED_DATA; + + case BZ_MEM_ERROR: + return ZIP_ER_MEMORY; + + case BZ_PARAM_ERROR: + return ZIP_ER_INVAL; + + case BZ_CONFIG_ERROR: /* actually, bzip2 miscompiled */ + case BZ_IO_ERROR: + case BZ_OUTBUFF_FULL: + case BZ_SEQUENCE_ERROR: + return ZIP_ER_INTERNAL; + + default: + return ZIP_ER_INTERNAL; + } + +} + +static bool +start(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + int ret; + + ctx->zstr.avail_in = 0; + ctx->zstr.next_in = NULL; + ctx->zstr.avail_out = 0; + ctx->zstr.next_out = NULL; + + if (ctx->compress) { + ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30); + + } + else { + ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0); + } + + if (ret != BZ_OK) { + zip_error_set(ctx->error, map_error(ret), 0); + return false; + } + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + int err; + + if (ctx->compress) { + err = BZ2_bzCompressEnd(&ctx->zstr); + } + else { + err = BZ2_bzDecompressEnd(&ctx->zstr); + } + + if (err != BZ_OK) { + zip_error_set(ctx->error, map_error(err), 0); + return false; + } + + return true; +} + + +static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length) { + struct ctx *ctx = (struct ctx *)ud; + + if (length > UINT_MAX || ctx->zstr.avail_in > 0) { + zip_error_set(ctx->error, ZIP_ER_INVAL, 0); + return false; + } + + ctx->zstr.avail_in = (unsigned int)length; + ctx->zstr.next_in = (char *)data; + + return true; +} + + +static void end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + + int ret; + + if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) { + *length = 0; + return ZIP_COMPRESSION_NEED_DATA; + } + + ctx->zstr.avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length); + ctx->zstr.next_out = (char *)data; + + if (ctx->compress) { + ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN); + } + else { + ret = BZ2_bzDecompress(&ctx->zstr); + } + + *length = *length - ctx->zstr.avail_out; + + switch (ret) { + case BZ_FINISH_OK: /* compression */ + return ZIP_COMPRESSION_OK; + + case BZ_OK: /* decompression */ + case BZ_RUN_OK: /* compression */ + if (ctx->zstr.avail_in == 0) { + return ZIP_COMPRESSION_NEED_DATA; + } + return ZIP_COMPRESSION_OK; + + case BZ_STREAM_END: + return ZIP_COMPRESSION_END; + + default: + zip_error_set(ctx->error, map_error(ret), 0); + return ZIP_COMPRESSION_ERROR; + } +} + + +zip_compression_algorithm_t zip_algorithm_bzip2_compress = { + compress_allocate, + deallocate, + compression_flags, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_bzip2_decompress = { + decompress_allocate, + deallocate, + compression_flags, + start, + end, + input, + end_of_input, + process +}; + +#else + +static int dummy __attribute__((used)); + +#endif /* HAVE_LIBBZ2 */ diff --git a/app/jni/zip_algorithm_deflate.c b/app/jni/zip_algorithm_deflate.c new file mode 100644 index 0000000..55cd928 --- /dev/null +++ b/app/jni/zip_algorithm_deflate.c @@ -0,0 +1,242 @@ +/* + zip_algorithm_deflate.c -- deflate (de)compression routines + Copyright (C) 2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include +#include + +struct ctx { + zip_error_t *error; + bool compress; + int compression_flags; + bool end_of_input; + z_stream zstr; +}; + + +static void * +allocate(bool compress, int compression_flags, zip_error_t *error) { + struct ctx *ctx; + + if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + + ctx->error = error; + ctx->compress = compress; + ctx->compression_flags = compression_flags; + if (ctx->compression_flags < 1 || ctx->compression_flags > 9) { + ctx->compression_flags = Z_BEST_COMPRESSION; + } + ctx->end_of_input = false; + + ctx->zstr.zalloc = Z_NULL; + ctx->zstr.zfree = Z_NULL; + ctx->zstr.opaque = NULL; + + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(true, compression_flags, error); +} + + +static void * +decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) { + return allocate(false, compression_flags, error); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + free(ctx); +} + + +static int +compression_flags(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + if (!ctx->compress) { + return 0; + } + + if (ctx->compression_flags < 3) { + return 2; + } + else if (ctx->compression_flags > 7) { + return 1; + } + return 0; +} + + +static bool +start(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + int ret; + + ctx->zstr.avail_in = 0; + ctx->zstr.next_in = NULL; + ctx->zstr.avail_out = 0; + ctx->zstr.next_out = NULL; + + if (ctx->compress) { + /* negative value to tell zlib not to write a header */ + ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); + } + else { + ret = inflateInit2(&ctx->zstr, -MAX_WBITS); + } + + if (ret != Z_OK) { + zip_error_set(ctx->error, ZIP_ER_ZLIB, ret); + return false; + } + + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + int err; + + if (ctx->compress) { + err = deflateEnd(&ctx->zstr); + } + else { + err = inflateEnd(&ctx->zstr); + } + + if (err != Z_OK) { + zip_error_set(ctx->error, ZIP_ER_ZLIB, err); + return false; + } + + return true; +} + + +static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length) { + struct ctx *ctx = (struct ctx *)ud; + + if (length > UINT_MAX || ctx->zstr.avail_in > 0) { + zip_error_set(ctx->error, ZIP_ER_INVAL, 0); + return false; + } + + ctx->zstr.avail_in = (uInt)length; + ctx->zstr.next_in = (Bytef *)data; + + return true; +} + + +static void end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + + int ret; + + ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length); + ctx->zstr.next_out = (Bytef *)data; + + if (ctx->compress) { + ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0); + } + else { + ret = inflate(&ctx->zstr, Z_SYNC_FLUSH); + } + + *length = *length - ctx->zstr.avail_out; + + switch (ret) { + case Z_OK: + return ZIP_COMPRESSION_OK; + + case Z_STREAM_END: + return ZIP_COMPRESSION_END; + + case Z_BUF_ERROR: + if (ctx->zstr.avail_in == 0) { + return ZIP_COMPRESSION_NEED_DATA; + } + + /* fallthrough */ + + default: + zip_error_set(ctx->error, ZIP_ER_ZLIB, ret); + return ZIP_COMPRESSION_ERROR; + } +} + + +zip_compression_algorithm_t zip_algorithm_deflate_compress = { + compress_allocate, + deallocate, + compression_flags, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_deflate_decompress = { + decompress_allocate, + deallocate, + compression_flags, + start, + end, + input, + end_of_input, + process +}; diff --git a/app/jni/zip_buffer.c b/app/jni/zip_buffer.c new file mode 100644 index 0000000..7addc4b --- /dev/null +++ b/app/jni/zip_buffer.c @@ -0,0 +1,348 @@ +/* + zip_buffer.c -- bounds checked access to memory buffer + Copyright (C) 2014-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "zipint.h" + +zip_uint8_t * +_zip_buffer_data(zip_buffer_t *buffer) +{ + return buffer->data; +} + + +void +_zip_buffer_free(zip_buffer_t *buffer) +{ + if (buffer == NULL) { + return; + } + + if (buffer->free_data) { + free(buffer->data); + } + + free(buffer); +} + + +bool +_zip_buffer_eof(zip_buffer_t *buffer) +{ + return buffer->ok && buffer->offset == buffer->size; +} + + +zip_uint8_t * +_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) +{ + zip_uint8_t *data; + + data = _zip_buffer_peek(buffer, length); + + if (data != NULL) { + buffer->offset += length; + } + + return data; +} + + +zip_uint16_t +_zip_buffer_get_16(zip_buffer_t *buffer) +{ + zip_uint8_t *data = _zip_buffer_get(buffer, 2); + + if (data == NULL) { + return 0; + } + + return (zip_uint16_t)(data[0] + (data[1] << 8)); +} + + +zip_uint32_t +_zip_buffer_get_32(zip_buffer_t *buffer) +{ + zip_uint8_t *data = _zip_buffer_get(buffer, 4); + + if (data == NULL) { + return 0; + } + + return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0]; +} + + +zip_uint64_t +_zip_buffer_get_64(zip_buffer_t *buffer) +{ + zip_uint8_t *data = _zip_buffer_get(buffer, 8); + + if (data == NULL) { + return 0; + } + + return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0]; +} + + + +zip_uint8_t +_zip_buffer_get_8(zip_buffer_t *buffer) +{ + zip_uint8_t *data = _zip_buffer_get(buffer, 1); + + if (data == NULL) { + return 0; + } + + return data[0]; +} + + +zip_uint64_t +_zip_buffer_left(zip_buffer_t *buffer) +{ + return buffer->ok ? buffer->size - buffer->offset : 0; +} + + +zip_uint64_t +_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) +{ + if (_zip_buffer_left(buffer) < length) { + length = _zip_buffer_left(buffer); + } + + memcpy(data, _zip_buffer_get(buffer, length), length); + + return length; +} + + +zip_buffer_t * +_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) +{ + bool free_data = (data == NULL); + zip_buffer_t *buffer; + + if (data == NULL) { + if ((data = (zip_uint8_t *)malloc(size)) == NULL) { + return NULL; + } + } + + if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) { + if (free_data) { + free(data); + } + return NULL; + } + + buffer->ok = true; + buffer->data = data; + buffer->size = size; + buffer->offset = 0; + buffer->free_data = free_data; + + return buffer; +} + + +zip_buffer_t * +_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error) +{ + zip_buffer_t *buffer; + + if ((buffer = _zip_buffer_new(buf, size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (_zip_read(src, buffer->data, size, error) < 0) { + _zip_buffer_free(buffer); + return NULL; + } + + return buffer; +} + + +zip_uint64_t +_zip_buffer_offset(zip_buffer_t *buffer) +{ + return buffer->ok ? buffer->offset : 0; +} + + +bool +_zip_buffer_ok(zip_buffer_t *buffer) +{ + return buffer->ok; +} + + + +zip_uint8_t * +_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) +{ + zip_uint8_t *data; + + if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) { + buffer->ok = false; + return NULL; + } + + data = buffer->data + buffer->offset; + return data; +} + +int +_zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) +{ + zip_uint8_t *dst = _zip_buffer_get(buffer, length); + + if (dst == NULL) { + return -1; + } + + memcpy(dst, src, length); + return 0; +} + + +int +_zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) +{ + zip_uint8_t *data = _zip_buffer_get(buffer, 2); + + if (data == NULL) { + return -1; + } + + data[0] = (zip_uint8_t)(i & 0xff); + data[1] = (zip_uint8_t)((i >> 8) & 0xff); + + return 0; +} + + +int +_zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) +{ + zip_uint8_t *data = _zip_buffer_get(buffer, 4); + + if (data == NULL) { + return -1; + } + + data[0] = (zip_uint8_t)(i & 0xff); + data[1] = (zip_uint8_t)((i >> 8) & 0xff); + data[2] = (zip_uint8_t)((i >> 16) & 0xff); + data[3] = (zip_uint8_t)((i >> 24) & 0xff); + + return 0; +} + + +int +_zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) +{ + zip_uint8_t *data = _zip_buffer_get(buffer, 8); + + if (data == NULL) { + return -1; + } + + data[0] = (zip_uint8_t)(i & 0xff); + data[1] = (zip_uint8_t)((i >> 8) & 0xff); + data[2] = (zip_uint8_t)((i >> 16) & 0xff); + data[3] = (zip_uint8_t)((i >> 24) & 0xff); + data[4] = (zip_uint8_t)((i >> 32) & 0xff); + data[5] = (zip_uint8_t)((i >> 40) & 0xff); + data[6] = (zip_uint8_t)((i >> 48) & 0xff); + data[7] = (zip_uint8_t)((i >> 56) & 0xff); + + return 0; +} + + +int +_zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) +{ + zip_uint8_t *data = _zip_buffer_get(buffer, 1); + + if (data == NULL) { + return -1; + } + + data[0] = i; + + return 0; +} + + +int +_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) +{ + if (offset > buffer->size) { + buffer->ok = false; + return -1; + } + + buffer->ok = true; + buffer->offset = offset; + + return 0; +} + + +int +_zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) { + zip_uint64_t offset = buffer->offset + length; + + if (offset < buffer->offset) { + buffer->ok = false; + return -1; + } + return _zip_buffer_set_offset(buffer, offset); +} + +zip_uint64_t +_zip_buffer_size(zip_buffer_t *buffer) +{ + return buffer->size; +} diff --git a/app/jni/zip_close.c b/app/jni/zip_close.c new file mode 100644 index 0000000..a4b1761 --- /dev/null +++ b/app/jni/zip_close.c @@ -0,0 +1,631 @@ +/* + zip_close.c -- close zip archive and update changes + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +#include +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#ifdef _WIN32 +#include +#include +#endif + + +static int add_data(zip_t *, zip_source_t *, zip_dirent_t *); +static int copy_data(zip_t *, zip_uint64_t); +static int copy_source(zip_t *, zip_source_t *, zip_int64_t); +static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t); + +ZIP_EXTERN int +zip_close(zip_t *za) +{ + zip_uint64_t i, j, survivors, unchanged_offset; + zip_int64_t off; + int error; + zip_filelist_t *filelist; + int changed; + + if (za == NULL) + return -1; + + changed = _zip_changed(za, &survivors); + + /* don't create zip files with no entries */ + if (survivors == 0) { + if ((za->open_flags & ZIP_TRUNCATE) || changed) { + if (zip_source_remove(za->src) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + } + zip_discard(za); + return 0; + } + + if (!changed) { + zip_discard(za); + return 0; + } + + if (survivors > za->nentry) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((filelist=(zip_filelist_t *)malloc(sizeof(filelist[0])*(size_t)survivors)) == NULL) + return -1; + + unchanged_offset = ZIP_UINT64_MAX; + /* create list of files with index into original archive */ + for (i=j=0; inentry; i++) { + if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) { + unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset); + } + if (za->entry[i].deleted) { + continue; + } + + if (j >= survivors) { + free(filelist); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + filelist[j].idx = i; + j++; + } + if (j < survivors) { + free(filelist); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) { + unchanged_offset = 0; + } + else { + if (unchanged_offset == ZIP_UINT64_MAX) { + /* we're keeping all file data, find the end of the last one */ + zip_uint64_t last_index = ZIP_UINT64_MAX; + unchanged_offset = 0; + + for (i = 0; i < za->nentry; i++) { + if (za->entry[i].orig != NULL) { + if (za->entry[i].orig->offset >= unchanged_offset) { + unchanged_offset = za->entry[i].orig->offset; + last_index = i; + } + } + } + if (last_index != ZIP_UINT64_MAX) { + if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) { + free(filelist); + return -1; + } + } + } + if (unchanged_offset > 0) { + if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) { + /* cloning not supported, need to copy everything */ + unchanged_offset = 0; + } + } + } + if (unchanged_offset == 0) { + if (zip_source_begin_write(za->src) < 0) { + _zip_error_set_from_source(&za->error, za->src); + free(filelist); + return -1; + } + } + + _zip_progress_start(za->progress); + error = 0; + for (j=0; jprogress, (double)j / (double)survivors, (double)(j+1) / (double)survivors); + + i = filelist[j].idx; + entry = za->entry+i; + + if (entry->orig != NULL && entry->orig->offset < unchanged_offset) { + /* already implicitly copied by cloning */ + continue; + } + + new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)); + + /* create new local directory entry */ + if (entry->changes == NULL) { + if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + error = 1; + break; + } + } + de = entry->changes; + + if (_zip_read_local_ef(za, i) < 0) { + error = 1; + break; + } + + if ((off = zip_source_tell_write(za->src)) < 0) { + error = 1; + break; + } + de->offset = (zip_uint64_t)off; + + if (new_data) { + zip_source_t *zs; + + zs = NULL; + if (!ZIP_ENTRY_DATA_CHANGED(entry)) { + if ((zs=_zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) { + error = 1; + break; + } + } + + /* add_data writes dirent */ + if (add_data(za, zs ? zs : entry->source, de) < 0) { + error = 1; + if (zs) + zip_source_free(zs); + break; + } + if (zs) + zip_source_free(zs); + } + else { + zip_uint64_t offset; + + /* when copying data, all sizes are known -> no data descriptor needed */ + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; + if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) { + error = 1; + break; + } + if ((offset=_zip_file_get_offset(za, i, &za->error)) == 0) { + error = 1; + break; + } + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + _zip_error_set_from_source(&za->error, za->src); + error = 1; + break; + } + if (copy_data(za, de->comp_size) < 0) { + error = 1; + break; + } + } + } + + if (!error) { + if (write_cdir(za, filelist, survivors) < 0) + error = 1; + } + + free(filelist); + + if (!error) { + if (zip_source_commit_write(za->src) != 0) { + _zip_error_set_from_source(&za->error, za->src); + error = 1; + } + } + + _zip_progress_end(za->progress); + + if (error) { + zip_source_rollback_write(za->src); + return -1; + } + + zip_discard(za); + + return 0; +} + + +static int +add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) +{ + zip_int64_t offstart, offdata, offend, data_length; + struct zip_stat st; + zip_source_t *src_final, *src_tmp; + int ret; + int is_zip64; + zip_flags_t flags; + zip_int8_t compression_flags; + bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt; + + if (zip_source_stat(src, &st) < 0) { + _zip_error_set_from_source(&za->error, src); + return -1; + } + + if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) { + st.valid |= ZIP_STAT_COMP_METHOD; + st.comp_method = ZIP_CM_STORE; + } + + if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE) + de->comp_method = st.comp_method; + else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) { + st.valid |= ZIP_STAT_COMP_SIZE; + st.comp_size = st.size; + } + else { + /* we'll recompress */ + st.valid &= ~ZIP_STAT_COMP_SIZE; + } + + if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) { + st.valid |= ZIP_STAT_ENCRYPTION_METHOD; + st.encryption_method = ZIP_EM_NONE; + } + + flags = ZIP_EF_LOCAL; + + if ((st.valid & ZIP_STAT_SIZE) == 0) { + flags |= ZIP_FL_FORCE_ZIP64; + data_length = -1; + } + else { + de->uncomp_size = st.size; + /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */ + data_length = (zip_int64_t)st.size; + + if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) { + zip_uint64_t max_size; + + switch (ZIP_CM_ACTUAL(de->comp_method)) { + case ZIP_CM_BZIP2: + /* computed by looking at increase of 10 random files of size 1MB when + * compressed with bzip2, rounded up: 1.006 */ + max_size = 4269351188u; + break; + + case ZIP_CM_DEFLATE: + /* max deflate size increase: size + ceil(size/16k)*5+6 */ + max_size = 4293656963u; + break; + + case ZIP_CM_STORE: + max_size = 0xffffffffu; + break; + + default: + max_size = 0; + } + + if (st.size > max_size) { + flags |= ZIP_FL_FORCE_ZIP64; + } + } + else + de->comp_size = st.comp_size; + } + + if ((offstart = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + + /* as long as we don't support non-seekable output, clear data descriptor bit */ + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; + if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) { + return -1; + } + + needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method); + needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE); + needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress; + needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE); + + needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method); + needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE); + needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE); + + src_final = src; + zip_source_keep(src_final); + + if (needs_decrypt) { + zip_encryption_implementation impl; + + if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_source_free(src_final); + return -1; + } + if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) { + /* error set by impl */ + zip_source_free(src_final); + return -1; + } + + zip_source_free(src_final); + src_final = src_tmp; + } + + if (needs_decompress) { + if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) { + zip_source_free(src_final); + return -1; + } + + zip_source_free(src_final); + src_final = src_tmp; + } + + if (needs_crc) { + if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) { + zip_source_free(src_final); + return -1; + } + + zip_source_free(src_final); + src_final = src_tmp; + } + + if (needs_compress) { + if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) { + zip_source_free(src_final); + return -1; + } + + zip_source_free(src_final); + src_final = src_tmp; + } + + + if (needs_encrypt) { + zip_encryption_implementation impl; + const char *password = NULL; + + if (de->password) { + password = de->password; + } else if (za->default_password) { + password = za->default_password; + } + + if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_source_free(src_final); + return -1; + } + if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) { + /* error set by impl */ + zip_source_free(src_final); + return -1; + } + + zip_source_free(src_final); + src_final = src_tmp; + } + + + if ((offdata = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + + ret = copy_source(za, src_final, data_length); + + if (zip_source_stat(src_final, &st) < 0) { + _zip_error_set_from_source(&za->error, src_final); + ret = -1; + } + + if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) { + _zip_error_set_from_source(&za->error, src_final); + ret = -1; + } + + zip_source_free(src_final); + + if (ret < 0) { + return -1; + } + + if ((offend = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + + if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + + if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) { + if (st.valid & ZIP_STAT_MTIME) + de->last_mod = st.mtime; + else + time(&de->last_mod); + } + de->comp_method = st.comp_method; + de->crc = st.crc; + de->uncomp_size = st.size; + de->comp_size = (zip_uint64_t)(offend - offdata); + de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1)); + _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0); + + if ((ret=_zip_dirent_write(za, de, flags)) < 0) + return -1; + + if (is_zip64 != ret) { + /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + + return 0; +} + + +static int +copy_data(zip_t *za, zip_uint64_t len) +{ + zip_uint8_t buf[BUFSIZE]; + size_t n; + double total = (double)len; + + while (len > 0) { + n = len > sizeof(buf) ? sizeof(buf) : len; + if (_zip_read(za->src, buf, n, &za->error) < 0) { + return -1; + } + + if (_zip_write(za, buf, n) < 0) { + return -1; + } + + len -= n; + + _zip_progress_update(za->progress, (total - (double)len) / total); + } + + return 0; +} + + +static int +copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) +{ + zip_uint8_t buf[BUFSIZE]; + zip_int64_t n, current; + int ret; + + if (zip_source_open(src) < 0) { + _zip_error_set_from_source(&za->error, src); + return -1; + } + + ret = 0; + current = 0; + while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) { + if (_zip_write(za, buf, (zip_uint64_t)n) < 0) { + ret = -1; + break; + } + if (n == sizeof(buf) && za->progress && data_length > 0) { + current += n; + _zip_progress_update(za->progress, (double)current/(double)data_length); + } + } + + if (n < 0) { + _zip_error_set_from_source(&za->error, src); + ret = -1; + } + + zip_source_close(src); + + return ret; +} + +static int +write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) +{ + zip_int64_t cd_start, end, size; + + if ((cd_start = zip_source_tell_write(za->src)) < 0) { + return -1; + } + + if ((size=_zip_cdir_write(za, filelist, survivors)) < 0) { + return -1; + } + + if ((end = zip_source_tell_write(za->src)) < 0) { + return -1; + } + + return 0; +} + + +int +_zip_changed(const zip_t *za, zip_uint64_t *survivorsp) +{ + int changed; + zip_uint64_t i, survivors; + + changed = 0; + survivors = 0; + + if (za->comment_changed || za->ch_flags != za->flags) { + changed = 1; + } + + for (i=0; inentry; i++) { + if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) { + changed = 1; + } + if (!za->entry[i].deleted) { + survivors++; + } + } + + if (survivorsp) { + *survivorsp = survivors; + } + + return changed; +} diff --git a/app/jni/zip_delete.c b/app/jni/zip_delete.c new file mode 100644 index 0000000..e160210 --- /dev/null +++ b/app/jni/zip_delete.c @@ -0,0 +1,70 @@ +/* + zip_delete.c -- delete file from zip archive + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_delete(zip_t *za, zip_uint64_t idx) +{ + const char *name; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((name=_zip_get_name(za, idx, 0, &za->error)) == NULL) { + return -1; + } + + if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) { + return -1; + } + + /* allow duplicate file names, because the file will + * be removed directly afterwards */ + if (_zip_unchange(za, idx, 1) != 0) + return -1; + + za->entry[idx].deleted = 1; + + return 0; +} + diff --git a/app/jni/zip_dir_add.c b/app/jni/zip_dir_add.c new file mode 100644 index 0000000..f535b21 --- /dev/null +++ b/app/jni/zip_dir_add.c @@ -0,0 +1,93 @@ +/* + zip_dir_add.c -- add directory + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +ZIP_EXTERN zip_int64_t +zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) +{ + size_t len; + zip_int64_t idx; + char *s; + zip_source_t *source; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (name == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + s = NULL; + len = strlen(name); + + if (name[len-1] != '/') { + if ((s=(char *)malloc(len+2)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + strcpy(s, name); + s[len] = '/'; + s[len+1] = '\0'; + } + + if ((source=zip_source_buffer(za, NULL, 0, 0)) == NULL) { + free(s); + return -1; + } + + idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags); + + free(s); + + if (idx < 0) + zip_source_free(source); + else { + if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) { + zip_delete(za, (zip_uint64_t)idx); + return -1; + } + } + + return idx; +} diff --git a/app/jni/zip_dirent.c b/app/jni/zip_dirent.c new file mode 100644 index 0000000..b9feb84 --- /dev/null +++ b/app/jni/zip_dirent.c @@ -0,0 +1,1139 @@ +/* + zip_dirent.c -- read directory entry (local or central), clean dirent + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include +#include +#include +#include + +#include "zipint.h" + +static time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t); +static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str); +static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *); +static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error); + + +void +_zip_cdir_free(zip_cdir_t *cd) +{ + zip_uint64_t i; + + if (!cd) + return; + + for (i=0; inentry; i++) + _zip_entry_finalize(cd->entry+i); + free(cd->entry); + _zip_string_free(cd->comment); + free(cd); +} + + +zip_cdir_t * +_zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) +{ + zip_cdir_t *cd; + + if ((cd=(zip_cdir_t *)malloc(sizeof(*cd))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + cd->entry = NULL; + cd->nentry = cd->nentry_alloc = 0; + cd->size = cd->offset = 0; + cd->comment = NULL; + cd->is_zip64 = false; + + if (!_zip_cdir_grow(cd, nentry, error)) { + _zip_cdir_free(cd); + return NULL; + } + + return cd; +} + + +bool +_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) +{ + zip_uint64_t i, new_alloc; + zip_entry_t *new_entry; + + if (additional_entries == 0) { + return true; + } + + new_alloc = cd->nentry_alloc + additional_entries; + + if (new_alloc < additional_entries || new_alloc > SIZE_MAX/sizeof(*(cd->entry))) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry))*(size_t)new_alloc)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + cd->entry = new_entry; + + for (i = cd->nentry; i < new_alloc; i++) { + _zip_entry_init(cd->entry+i); + } + + cd->nentry = cd->nentry_alloc = new_alloc; + + return true; +} + + +zip_int64_t +_zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) +{ + zip_uint64_t offset, size; + zip_string_t *comment; + zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN]; + zip_buffer_t *buffer; + zip_int64_t off; + zip_uint64_t i; + bool is_zip64; + int ret; + + if ((off = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + offset = (zip_uint64_t)off; + + is_zip64 = false; + + for (i=0; ientry+filelist[i].idx; + + if ((ret=_zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0) + return -1; + if (ret) + is_zip64 = true; + } + + if ((off = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + size = (zip_uint64_t)off - offset; + + if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX) + is_zip64 = true; + + + if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if (is_zip64) { + _zip_buffer_put(buffer, EOCD64_MAGIC, 4); + _zip_buffer_put_64(buffer, EOCD64LEN-12); + _zip_buffer_put_16(buffer, 45); + _zip_buffer_put_16(buffer, 45); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_64(buffer, survivors); + _zip_buffer_put_64(buffer, survivors); + _zip_buffer_put_64(buffer, size); + _zip_buffer_put_64(buffer, offset); + _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_64(buffer, offset+size); + _zip_buffer_put_32(buffer, 1); + } + + _zip_buffer_put(buffer, EOCD_MAGIC, 4); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors)); + _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors)); + _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size); + _zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset); + + comment = za->comment_changed ? za->comment_changes : za->comment_orig; + + _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0)); + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; + } + + if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) { + _zip_buffer_free(buffer); + return -1; + } + + _zip_buffer_free(buffer); + + if (comment) { + if (_zip_write(za, comment->raw, comment->length) < 0) { + return -1; + } + } + + return (zip_int64_t)size; +} + + +zip_dirent_t * +_zip_dirent_clone(const zip_dirent_t *sde) +{ + zip_dirent_t *tde; + + if ((tde=(zip_dirent_t *)malloc(sizeof(*tde))) == NULL) + return NULL; + + if (sde) + memcpy(tde, sde, sizeof(*sde)); + else + _zip_dirent_init(tde); + + tde->changed = 0; + tde->cloned = 1; + + return tde; +} + + +void +_zip_dirent_finalize(zip_dirent_t *zde) +{ + if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(zde->filename); + zde->filename = NULL; + } + if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) { + _zip_ef_free(zde->extra_fields); + zde->extra_fields = NULL; + } + if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) { + _zip_string_free(zde->comment); + zde->comment = NULL; + } + if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) { + if (zde->password) { + _zip_crypto_clear(zde->password, strlen(zde->password)); + } + free(zde->password); + zde->password = NULL; + } +} + + +void +_zip_dirent_free(zip_dirent_t *zde) +{ + if (zde == NULL) + return; + + _zip_dirent_finalize(zde); + free(zde); +} + + +void +_zip_dirent_init(zip_dirent_t *de) +{ + de->changed = 0; + de->local_extra_fields_read = 0; + de->cloned = 0; + + de->crc_valid = true; + de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8); + de->version_needed = 10; /* 1.0 */ + de->bitflags = 0; + de->comp_method = ZIP_CM_DEFAULT; + de->last_mod = 0; + de->crc = 0; + de->comp_size = 0; + de->uncomp_size = 0; + de->filename = NULL; + de->extra_fields = NULL; + de->comment = NULL; + de->disk_number = 0; + de->int_attrib = 0; + de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT; + de->offset = 0; + de->compression_level = 0; + de->encryption_method = ZIP_EM_NONE; + de->password = NULL; +} + + +bool +_zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) +{ + if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX + || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX)) + return true; + + return false; +} + + +zip_dirent_t * +_zip_dirent_new(void) +{ + zip_dirent_t *de; + + if ((de=(zip_dirent_t *)malloc(sizeof(*de))) == NULL) + return NULL; + + _zip_dirent_init(de); + return de; +} + + +/* _zip_dirent_read(zde, fp, bufp, left, localp, error): + Fills the zip directory entry zde. + + If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed. + + If local is true, it reads a local header instead of a central directory entry. + + Returns size of dirent read if successful. On error, error is filled in and -1 is returned. +*/ + +zip_int64_t +_zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error) +{ + zip_uint8_t buf[CDENTRYSIZE]; + zip_uint16_t dostime, dosdate; + zip_uint32_t size, variable_size; + zip_uint16_t filename_len, comment_len, ef_len; + + bool from_buffer = (buffer != NULL); + + size = local ? LENTRYSIZE : CDENTRYSIZE; + + if (buffer) { + if (_zip_buffer_left(buffer) < size) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + } + else { + if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) { + return -1; + } + } + + if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + + /* convert buffercontents to zip_dirent */ + + _zip_dirent_init(zde); + if (!local) + zde->version_madeby = _zip_buffer_get_16(buffer); + else + zde->version_madeby = 0; + zde->version_needed = _zip_buffer_get_16(buffer); + zde->bitflags = _zip_buffer_get_16(buffer); + zde->comp_method = _zip_buffer_get_16(buffer); + + /* convert to time_t */ + dostime = _zip_buffer_get_16(buffer); + dosdate = _zip_buffer_get_16(buffer); + zde->last_mod = _zip_d2u_time(dostime, dosdate); + + zde->crc = _zip_buffer_get_32(buffer); + zde->comp_size = _zip_buffer_get_32(buffer); + zde->uncomp_size = _zip_buffer_get_32(buffer); + + filename_len = _zip_buffer_get_16(buffer); + ef_len = _zip_buffer_get_16(buffer); + + if (local) { + comment_len = 0; + zde->disk_number = 0; + zde->int_attrib = 0; + zde->ext_attrib = 0; + zde->offset = 0; + } else { + comment_len = _zip_buffer_get_16(buffer); + zde->disk_number = _zip_buffer_get_16(buffer); + zde->int_attrib = _zip_buffer_get_16(buffer); + zde->ext_attrib = _zip_buffer_get_32(buffer); + zde->offset = _zip_buffer_get_32(buffer); + } + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + + if (zde->bitflags & ZIP_GPBF_ENCRYPTED) { + if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { + /* TODO */ + zde->encryption_method = ZIP_EM_UNKNOWN; + } + else { + zde->encryption_method = ZIP_EM_TRAD_PKWARE; + } + } + else { + zde->encryption_method = ZIP_EM_NONE; + } + + zde->filename = NULL; + zde->extra_fields = NULL; + zde->comment = NULL; + + variable_size = (zip_uint32_t)filename_len+(zip_uint32_t)ef_len+(zip_uint32_t)comment_len; + + if (from_buffer) { + if (_zip_buffer_left(buffer) < variable_size) { + zip_error_set(error, ZIP_ER_INCONS, 0); + return -1; + } + } + else { + _zip_buffer_free(buffer); + + if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) { + return -1; + } + } + + if (filename_len) { + zde->filename = _zip_read_string(buffer, src, filename_len, 1, error); + if (!zde->filename) { + if (zip_error_code_zip(error) == ZIP_ER_EOF) { + zip_error_set(error, ZIP_ER_INCONS, 0); + } + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + + if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { + if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { + zip_error_set(error, ZIP_ER_INCONS, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + } + } + + if (ef_len) { + zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error); + + if (ef == NULL) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) { + free(ef); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + free(ef); + if (local) + zde->local_extra_fields_read = 1; + } + + if (comment_len) { + zde->comment = _zip_read_string(buffer, src, comment_len, 0, error); + if (!zde->comment) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { + if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { + zip_error_set(error, ZIP_ER_INCONS, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + } + } + + zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename); + zde->comment = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment); + + /* Zip64 */ + + if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) { + zip_uint16_t got_len; + zip_buffer_t *ef_buffer; + const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error); + /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */ + if (ef == NULL) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + + if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + + if (zde->uncomp_size == ZIP_UINT32_MAX) + zde->uncomp_size = _zip_buffer_get_64(ef_buffer); + else if (local) { + /* From appnote.txt: This entry in the Local header MUST + include BOTH original and compressed file size fields. */ + (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */ + } + if (zde->comp_size == ZIP_UINT32_MAX) + zde->comp_size = _zip_buffer_get_64(ef_buffer); + if (!local) { + if (zde->offset == ZIP_UINT32_MAX) + zde->offset = _zip_buffer_get_64(ef_buffer); + if (zde->disk_number == ZIP_UINT16_MAX) + zde->disk_number = _zip_buffer_get_32(buffer); + } + + if (!_zip_buffer_eof(ef_buffer)) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(ef_buffer); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + _zip_buffer_free(ef_buffer); + } + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + if (!from_buffer) { + _zip_buffer_free(buffer); + } + + /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */ + if (zde->offset > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return -1; + } + + if (!_zip_dirent_process_winzip_aes(zde, error)) { + return -1; + } + + zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); + + return (zip_int64_t)(size + variable_size); +} + + +static zip_string_t * +_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str) +{ + zip_uint16_t ef_len; + zip_uint32_t ef_crc; + zip_buffer_t *buffer; + + const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL); + + if (ef == NULL || ef_len < 5 || ef[0] != 1) { + return str; + } + + if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) { + return str; + } + + _zip_buffer_get_8(buffer); + ef_crc = _zip_buffer_get_32(buffer); + + if (_zip_string_crc32(str) == ef_crc) { + zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer); + zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL); + + if (ef_str != NULL) { + _zip_string_free(str); + str = ef_str; + } + } + + _zip_buffer_free(buffer); + + return str; +} + + +static bool +_zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) +{ + zip_uint16_t ef_len; + zip_buffer_t *buffer; + const zip_uint8_t *ef; + bool crc_valid; + zip_uint16_t enc_method; + + + if (de->comp_method != ZIP_CM_WINZIP_AES) { + return true; + } + + ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL); + + if (ef == NULL || ef_len < 7) { + zip_error_set(error, ZIP_ER_INCONS, 0); + return false; + } + + if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return false; + } + + /* version */ + + crc_valid = true; + switch (_zip_buffer_get_16(buffer)) { + case 1: + break; + + case 2: + if (de->uncomp_size < 20 /* TODO: constant */) { + crc_valid = false; + } + break; + + default: + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; + } + + /* vendor */ + if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) { + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; + } + + /* mode */ + switch (_zip_buffer_get_8(buffer)) { + case 1: + enc_method = ZIP_EM_AES_128; + break; + case 2: + enc_method = ZIP_EM_AES_192; + break; + case 3: + enc_method = ZIP_EM_AES_256; + break; + default: + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; + } + + if (ef_len != 7) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(buffer); + return false; + } + + de->crc_valid = crc_valid; + de->encryption_method = enc_method; + de->comp_method = _zip_buffer_get_16(buffer); + + _zip_buffer_free(buffer); + return true; +} + + +zip_int32_t +_zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) +{ + zip_int32_t size; + bool local = (flags & ZIP_EF_LOCAL) != 0; + int i; + zip_uint8_t b[6]; + zip_buffer_t *buffer; + + size = local ? LENTRYSIZE : CDENTRYSIZE; + + if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) { + _zip_error_set_from_source(error, src); + return -1; + } + + if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) { + return -1; + } + + for (i=0; i<(local ? 2 : 3); i++) { + size += _zip_buffer_get_16(buffer); + } + + if (!_zip_buffer_eof(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; + } + + _zip_buffer_free(buffer); + return size; +} + + +/* _zip_dirent_write + Writes zip directory entry. + + If flags & ZIP_EF_LOCAL, it writes a local header instead of a central + directory entry. If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed. + + Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is + returned. +*/ + +int +_zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) +{ + zip_uint16_t dostime, dosdate; + zip_encoding_type_t com_enc, name_enc; + zip_extra_field_t *ef; + zip_extra_field_t *ef64; + zip_uint32_t ef_total_size; + bool is_zip64; + bool is_really_zip64; + bool is_winzip_aes; + zip_uint8_t buf[CDENTRYSIZE]; + zip_buffer_t *buffer; + + ef = NULL; + + name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN); + com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); + + if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || + (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || + (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN)) + de->bitflags |= ZIP_GPBF_ENCODING_UTF_8; + else { + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8; + if (name_enc == ZIP_ENCODING_UTF8_KNOWN) { + ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error); + if (ef == NULL) + return -1; + } + if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN){ + zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error); + if (ef2 == NULL) { + _zip_ef_free(ef); + return -1; + } + ef2->next = ef; + ef = ef2; + } + } + + if (de->encryption_method == ZIP_EM_NONE) { + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED; + } + else { + de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED; + } + + is_really_zip64 = _zip_dirent_needs_zip64(de, flags); + is_zip64 = (flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64) || is_really_zip64; + is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256; + + if (is_zip64) { + zip_uint8_t ef_zip64[EFZIP64SIZE]; + zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64)); + if (ef_buffer == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef); + return -1; + } + + if (flags & ZIP_FL_LOCAL) { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->uncomp_size); + _zip_buffer_put_64(ef_buffer, de->comp_size); + } + } + else { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) { + if (de->uncomp_size >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->uncomp_size); + } + if (de->comp_size >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->comp_size); + } + if (de->offset >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->offset); + } + } + } + + if (!_zip_buffer_ok(ef_buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(ef_buffer); + _zip_ef_free(ef); + return -1; + } + + ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH); + _zip_buffer_free(ef_buffer); + ef64->next = ef; + ef = ef64; + } + + if (is_winzip_aes) { + zip_uint8_t data[EF_WINZIP_AES_SIZE]; + zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data)); + zip_extra_field_t *ef_winzip; + + if (ef_buffer == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef); + return -1; + } + + _zip_buffer_put_16(ef_buffer, 2); + _zip_buffer_put(ef_buffer, "AE", 2); + _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff)); + _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method); + + if (!_zip_buffer_ok(ef_buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(ef_buffer); + _zip_ef_free(ef); + return -1; + } + + ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH); + _zip_buffer_free(ef_buffer); + ef_winzip->next = ef; + ef = ef_winzip; + } + + if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef); + return -1; + } + + _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4); + + if ((flags & ZIP_FL_LOCAL) == 0) { + _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby)); + } + _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed)); + _zip_buffer_put_16(buffer, de->bitflags); + if (is_winzip_aes) { + _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES); + } + else { + _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method); + } + + _zip_u2d_time(de->last_mod, &dostime, &dosdate); + _zip_buffer_put_16(buffer, dostime); + _zip_buffer_put_16(buffer, dosdate); + + if (is_winzip_aes && de->uncomp_size < 20) { + _zip_buffer_put_32(buffer, 0); + } + else { + _zip_buffer_put_32(buffer, de->crc); + } + + if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) { + /* In local headers, if a ZIP64 EF is written, it MUST contain + * both compressed and uncompressed sizes (even if one of the + * two is smaller than 0xFFFFFFFF); on the other hand, those + * may only appear when the corresponding standard entry is + * 0xFFFFFFFF. (appnote.txt 4.5.3) */ + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + else { + if (de->comp_size < ZIP_UINT32_MAX) { + _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size); + } + else { + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + if (de->uncomp_size < ZIP_UINT32_MAX) { + _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size); + } + else { + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + } + + _zip_buffer_put_16(buffer, _zip_string_length(de->filename)); + /* TODO: check for overflow */ + ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH); + _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size); + + if ((flags & ZIP_FL_LOCAL) == 0) { + _zip_buffer_put_16(buffer, _zip_string_length(de->comment)); + _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number); + _zip_buffer_put_16(buffer, de->int_attrib); + _zip_buffer_put_32(buffer, de->ext_attrib); + if (de->offset < ZIP_UINT32_MAX) + _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset); + else + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef); + return -1; + } + + if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) { + _zip_buffer_free(buffer); + _zip_ef_free(ef); + return -1; + } + + _zip_buffer_free(buffer); + + if (de->filename) { + if (_zip_string_write(za, de->filename) < 0) { + _zip_ef_free(ef); + return -1; + } + } + + if (ef) { + if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) { + _zip_ef_free(ef); + return -1; + } + } + _zip_ef_free(ef); + if (de->extra_fields) { + if (_zip_ef_write(za, de->extra_fields, flags) < 0) { + return -1; + } + } + + if ((flags & ZIP_FL_LOCAL) == 0) { + if (de->comment) { + if (_zip_string_write(za, de->comment) < 0) { + return -1; + } + } + } + + + return is_zip64; +} + + +static time_t +_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) +{ + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + + /* let mktime decide if DST is in effect */ + tm.tm_isdst = -1; + + tm.tm_year = ((ddate>>9)&127) + 1980 - 1900; + tm.tm_mon = ((ddate>>5)&15) - 1; + tm.tm_mday = ddate&31; + + tm.tm_hour = (dtime>>11)&31; + tm.tm_min = (dtime>>5)&63; + tm.tm_sec = (dtime<<1)&62; + + return mktime(&tm); +} + + +static zip_extra_field_t * +_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) +{ + const zip_uint8_t *raw; + zip_uint32_t len; + zip_buffer_t *buffer; + zip_extra_field_t *ef; + + if ((raw=_zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) { + /* error already set */ + return NULL; + } + + if (len+5 > ZIP_UINT16_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */ + return NULL; + } + + if ((buffer = _zip_buffer_new(NULL, len+5)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + _zip_buffer_put_8(buffer, 1); + _zip_buffer_put_32(buffer, _zip_string_crc32(str)); + _zip_buffer_put(buffer, raw, len); + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return NULL; + } + + ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH); + _zip_buffer_free(buffer); + + return ef; +} + + +zip_dirent_t * +_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) +{ + if (error == NULL) + error = &za->error; + + if (idx >= za->nentry) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) { + if (za->entry[idx].orig == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) { + zip_error_set(error, ZIP_ER_DELETED, 0); + return NULL; + } + return za->entry[idx].orig; + } + else + return za->entry[idx].changes; +} + + + + +void +_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) +{ + struct tm *tm; + + tm = localtime(&intime); + if (tm->tm_year < 80) { + tm->tm_year = 80; + } + + *ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday); + *dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1)); + + return; +} + + +void +_zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64) { + zip_uint16_t length; + + if (de->comp_method == ZIP_CM_LZMA) { + de->version_needed = 63; + return; + } + + if (de->comp_method == ZIP_CM_BZIP2) { + de->version_needed = 46; + return; + } + + if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) { + de->version_needed = 45; + return; + } + + if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) { + de->version_needed = 20; + return; + } + + /* directory */ + if ((length = _zip_string_length(de->filename)) > 0) { + if (de->filename->raw[length-1] == '/') { + de->version_needed = 20; + return; + } + } + + de->version_needed = 10; +} diff --git a/app/jni/zip_discard.c b/app/jni/zip_discard.c new file mode 100644 index 0000000..f0188b5 --- /dev/null +++ b/app/jni/zip_discard.c @@ -0,0 +1,81 @@ +/* + zip_discard.c -- discard and free struct zip + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +/* zip_discard: + frees the space allocated to a zipfile struct, and closes the + corresponding file. */ + +void +zip_discard(zip_t *za) +{ + zip_uint64_t i; + + if (za == NULL) + return; + + if (za->src) { + zip_source_close(za->src); + zip_source_free(za->src); + } + + free(za->default_password); + _zip_string_free(za->comment_orig); + _zip_string_free(za->comment_changes); + + _zip_hash_free(za->names); + + if (za->entry) { + for (i=0; inentry; i++) + _zip_entry_finalize(za->entry+i); + free(za->entry); + } + + for (i=0; inopen_source; i++) { + _zip_source_invalidate(za->open_source[i]); + } + free(za->open_source); + + _zip_progress_free(za->progress); + + zip_error_fini(&za->error); + + free(za); + + return; +} diff --git a/app/jni/zip_entry.c b/app/jni/zip_entry.c new file mode 100644 index 0000000..6f89006 --- /dev/null +++ b/app/jni/zip_entry.c @@ -0,0 +1,53 @@ +/* + zip_entry.c -- struct zip_entry helper functions + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +void +_zip_entry_finalize(zip_entry_t *e) +{ + _zip_unchange_data(e); + _zip_dirent_free(e->orig); + _zip_dirent_free(e->changes); +} + + +void +_zip_entry_init(zip_entry_t *e) +{ + e->orig = NULL; + e->changes = NULL; + e->source = NULL; + e->deleted = 0; +} diff --git a/app/jni/zip_err_str.c b/app/jni/zip_err_str.c new file mode 100644 index 0000000..724849b --- /dev/null +++ b/app/jni/zip_err_str.c @@ -0,0 +1,82 @@ +/* + This file was generated automatically by ./make_zip_err_str.sh + from ./zip.h; make changes there. + */ + +#include "zipint.h" + +const char * const _zip_err_str[] = { + "No error", + "Multi-disk zip archives not supported", + "Renaming temporary file failed", + "Closing zip archive failed", + "Seek error", + "Read error", + "Write error", + "CRC error", + "Containing zip archive was closed", + "No such file", + "File already exists", + "Can't open file", + "Failure to create temporary file", + "Zlib error", + "Malloc failure", + "Entry has been changed", + "Compression method not supported", + "Premature end of file", + "Invalid argument", + "Not a zip archive", + "Internal error", + "Zip archive inconsistent", + "Can't remove file", + "Entry has been deleted", + "Encryption method not supported", + "Read-only archive", + "No password provided", + "Wrong password provided", + "Operation not supported", + "Resource still in use", + "Tell error", + "Compressed data invalid", +}; + +const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]); + +#define N ZIP_ET_NONE +#define S ZIP_ET_SYS +#define Z ZIP_ET_ZLIB + +const int _zip_err_type[] = { + N, + N, + S, + S, + S, + S, + S, + N, + N, + N, + N, + S, + S, + Z, + N, + N, + N, + N, + N, + N, + N, + N, + S, + N, + N, + N, + N, + N, + N, + N, + S, + N, +}; diff --git a/app/jni/zip_error.c b/app/jni/zip_error.c new file mode 100644 index 0000000..5f4e07d --- /dev/null +++ b/app/jni/zip_error.c @@ -0,0 +1,155 @@ +/* + zip_error.c -- zip_error_t helper functions + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_error_code_system(const zip_error_t *error) { + return error->sys_err; +} + + +ZIP_EXTERN int +zip_error_code_zip(const zip_error_t *error) { + return error->zip_err; +} + + +ZIP_EXTERN void +zip_error_fini(zip_error_t *err) +{ + free(err->str); + err->str = NULL; +} + + +ZIP_EXTERN void +zip_error_init(zip_error_t *err) +{ + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; + err->str = NULL; +} + +ZIP_EXTERN void +zip_error_init_with_code(zip_error_t *error, int ze) +{ + zip_error_init(error); + error->zip_err = ze; + switch (zip_error_system_type(error)) { + case ZIP_ET_SYS: + error->sys_err = errno; + break; + + default: + error->sys_err = 0; + break; + } +} + + +ZIP_EXTERN int +zip_error_system_type(const zip_error_t *error) { + if (error->zip_err < 0 || error->zip_err >= _zip_nerr_str) + return ZIP_ET_NONE; + + return _zip_err_type[error->zip_err]; +} + + +void +_zip_error_clear(zip_error_t *err) +{ + if (err == NULL) + return; + + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; +} + + +void +_zip_error_copy(zip_error_t *dst, const zip_error_t *src) +{ + dst->zip_err = src->zip_err; + dst->sys_err = src->sys_err; +} + + +void +_zip_error_get(const zip_error_t *err, int *zep, int *sep) +{ + if (zep) + *zep = err->zip_err; + if (sep) { + if (zip_error_system_type(err) != ZIP_ET_NONE) + *sep = err->sys_err; + else + *sep = 0; + } +} + + +void +zip_error_set(zip_error_t *err, int ze, int se) +{ + if (err) { + err->zip_err = ze; + err->sys_err = se; + } +} + + +void +_zip_error_set_from_source(zip_error_t *err, zip_source_t *src) +{ + _zip_error_copy(err, zip_source_error(src)); +} + + +zip_int64_t +zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) +{ + int *e = (int *)data; + + if (length < sizeof(int)*2) { + return -1; + } + + e[0] = zip_error_code_zip(error); + e[1] = zip_error_code_system(error); + return sizeof(int)*2; +} diff --git a/app/jni/zip_error_clear.c b/app/jni/zip_error_clear.c new file mode 100644 index 0000000..ec45e68 --- /dev/null +++ b/app/jni/zip_error_clear.c @@ -0,0 +1,45 @@ +/* + zip_error_clear.c -- clear zip error + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN void +zip_error_clear(zip_t *za) +{ + if (za == NULL) + return; + + _zip_error_clear(&za->error); +} diff --git a/app/jni/zip_error_get.c b/app/jni/zip_error_get.c new file mode 100644 index 0000000..c222018 --- /dev/null +++ b/app/jni/zip_error_get.c @@ -0,0 +1,57 @@ +/* + zip_error_get.c -- get zip error + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN void +zip_error_get(zip_t *za, int *zep, int *sep) +{ + _zip_error_get(&za->error, zep, sep); +} + + +ZIP_EXTERN zip_error_t * +zip_get_error(zip_t *za) +{ + return &za->error; +} + + +ZIP_EXTERN zip_error_t * +zip_file_get_error(zip_file_t *f) +{ + return &f->error; +} diff --git a/app/jni/zip_error_get_sys_type.c b/app/jni/zip_error_get_sys_type.c new file mode 100644 index 0000000..7e27bbf --- /dev/null +++ b/app/jni/zip_error_get_sys_type.c @@ -0,0 +1,45 @@ +/* + zip_error_get_sys_type.c -- return type of system error code + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_error_get_sys_type(int ze) +{ + if (ze < 0 || ze >= _zip_nerr_str) + return 0; + + return _zip_err_type[ze]; +} diff --git a/app/jni/zip_error_strerror.c b/app/jni/zip_error_strerror.c new file mode 100644 index 0000000..bdc1e44 --- /dev/null +++ b/app/jni/zip_error_strerror.c @@ -0,0 +1,87 @@ +/* + zip_error_sterror.c -- get string representation of struct zip_error + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_error_strerror(zip_error_t *err) +{ + const char *zs, *ss; + char buf[128], *s; + + zip_error_fini(err); + + if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) { + sprintf(buf, "Unknown error %d", err->zip_err); + zs = NULL; + ss = buf; + } + else { + zs = _zip_err_str[err->zip_err]; + + switch (_zip_err_type[err->zip_err]) { + case ZIP_ET_SYS: + ss = strerror(err->sys_err); + break; + + case ZIP_ET_ZLIB: + ss = zError(err->sys_err); + break; + + default: + ss = NULL; + } + } + + if (ss == NULL) + return zs; + else { + if ((s=(char *)malloc(strlen(ss) + + (zs ? strlen(zs)+2 : 0) + 1)) == NULL) + return _zip_err_str[ZIP_ER_MEMORY]; + + sprintf(s, "%s%s%s", + (zs ? zs : ""), + (zs ? ": " : ""), + ss); + err->str = s; + + return s; + } +} diff --git a/app/jni/zip_error_to_str.c b/app/jni/zip_error_to_str.c new file mode 100644 index 0000000..019feff --- /dev/null +++ b/app/jni/zip_error_to_str.c @@ -0,0 +1,68 @@ +/* + zip_error_to_str.c -- get string representation of zip error code + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) +{ + const char *zs, *ss; + + if (ze < 0 || ze >= _zip_nerr_str) + return snprintf(buf, len, "Unknown error %d", ze); + + zs = _zip_err_str[ze]; + + switch (_zip_err_type[ze]) { + case ZIP_ET_SYS: + ss = strerror(se); + break; + + case ZIP_ET_ZLIB: + ss = zError(se); + break; + + default: + ss = NULL; + } + + return snprintf(buf, len, "%s%s%s", + zs, (ss ? ": " : ""), (ss ? ss : "")); +} diff --git a/app/jni/zip_extra_field.c b/app/jni/zip_extra_field.c new file mode 100644 index 0000000..92f36de --- /dev/null +++ b/app/jni/zip_extra_field.c @@ -0,0 +1,438 @@ +/* + zip_extra_field.c -- manipulate extra fields + Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "zipint.h" + + +zip_extra_field_t * +_zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) +{ + zip_extra_field_t *head, *prev, *def; + + head = prev = NULL; + + while (ef) { + if ((def=_zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_ef_free(head); + return NULL; + } + + if (head == NULL) + head = def; + if (prev) + prev->next = def; + prev = def; + + ef = ef->next; + } + + return head; +} + + +zip_extra_field_t * +_zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) +{ + zip_extra_field_t *head, *prev; + int i; + + i = 0; + head = ef; + prev = NULL; + for (; ef; ef=(prev ? prev->next : head)) { + if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) { + if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) { + ef->flags &= ~(flags & ZIP_EF_BOTH); + if ((ef->flags & ZIP_EF_BOTH) == 0) { + if (prev) + prev->next = ef->next; + else + head = ef->next; + ef->next = NULL; + _zip_ef_free(ef); + + if (id_idx == ZIP_EXTRA_FIELD_ALL) + continue; + } + } + + i++; + if (i > id_idx) + break; + } + prev = ef; + } + + return head; +} + + + +void +_zip_ef_free(zip_extra_field_t *ef) +{ + zip_extra_field_t *ef2; + + while (ef) { + ef2 = ef->next; + free(ef->data); + free(ef); + ef = ef2; + } +} + + +const zip_uint8_t * +_zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, zip_error_t *error) +{ + static const zip_uint8_t empty[1] = { '\0' }; + + int i; + + i = 0; + for (; ef; ef=ef->next) { + if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) { + if (i < id_idx) { + i++; + continue; + } + + if (lenp) + *lenp = ef->size; + if (ef->size > 0) + return ef->data; + else + return empty; + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + return NULL; +} + + +zip_extra_field_t * +_zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) +{ + zip_extra_field_t *ef2, *tt, *tail; + int duplicate; + + if (to == NULL) + return from; + + for (tail=to; tail->next; tail=tail->next) + ; + + for (; from; from=ef2) { + ef2 = from->next; + + duplicate = 0; + for (tt=to; tt; tt=tt->next) { + if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) { + tt->flags |= (from->flags & ZIP_EF_BOTH); + duplicate = 1; + break; + } + } + + from->next = NULL; + if (duplicate) + _zip_ef_free(from); + else + tail = tail->next = from; + } + + return to; +} + + +zip_extra_field_t * +_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) +{ + zip_extra_field_t *ef; + + if ((ef=(zip_extra_field_t *)malloc(sizeof(*ef))) == NULL) + return NULL; + + ef->next = NULL; + ef->flags = flags; + ef->id = id; + ef->size = size; + if (size > 0) { + if ((ef->data=(zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) { + free(ef); + return NULL; + } + } + else + ef->data = NULL; + + return ef; +} + + +bool +_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error) +{ + zip_buffer_t *buffer; + zip_extra_field_t *ef, *ef2, *ef_head; + + if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + ef_head = ef = NULL; + + while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) { + zip_uint16_t fid, flen; + zip_uint8_t *ef_data; + + fid = _zip_buffer_get_16(buffer); + flen = _zip_buffer_get_16(buffer); + ef_data = _zip_buffer_get(buffer, flen); + + if (ef_data == NULL) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } + + if ((ef2=_zip_ef_new(fid, flen, ef_data, flags)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } + + if (ef_head) { + ef->next = ef2; + ef = ef2; + } + else + ef_head = ef = ef2; + } + + if (!_zip_buffer_eof(buffer)) { + /* Android APK files align stored file data with padding in extra fields; ignore. */ + /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */ + size_t glen = _zip_buffer_left(buffer); + zip_uint8_t *garbage; + garbage = _zip_buffer_get(buffer, glen); + if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } + } + + _zip_buffer_free(buffer); + + if (ef_head_p) { + *ef_head_p = ef_head; + } + else { + _zip_ef_free(ef_head); + } + + return true; +} + + +zip_extra_field_t * +_zip_ef_remove_internal(zip_extra_field_t *ef) +{ + zip_extra_field_t *ef_head; + zip_extra_field_t *prev, *next; + + ef_head = ef; + prev = NULL; + + while (ef) { + if (ZIP_EF_IS_INTERNAL(ef->id)) { + next = ef->next; + if (ef_head == ef) + ef_head = next; + ef->next = NULL; + _zip_ef_free(ef); + if (prev) + prev->next = next; + ef = next; + } + else { + prev = ef; + ef = ef->next; + } + } + + return ef_head; +} + + +zip_uint16_t +_zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) +{ + zip_uint16_t size; + + size = 0; + for (; ef; ef=ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) + size = (zip_uint16_t)(size+4+ef->size); + } + + return size; +} + + +int +_zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) +{ + zip_uint8_t b[4]; + zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b)); + + if (buffer == NULL) { + return -1; + } + + for (; ef; ef=ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) { + _zip_buffer_set_offset(buffer, 0); + _zip_buffer_put_16(buffer, ef->id); + _zip_buffer_put_16(buffer, ef->size); + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; + } + if (_zip_write(za, b, 4) < 0) { + _zip_buffer_free(buffer); + return -1; + } + if (ef->size > 0) { + if (_zip_write(za, ef->data, ef->size) < 0) { + _zip_buffer_free(buffer); + return -1; + } + } + } + } + + _zip_buffer_free(buffer); + return 0; +} + + +int +_zip_read_local_ef(zip_t *za, zip_uint64_t idx) +{ + zip_entry_t *e; + unsigned char b[4]; + zip_buffer_t *buffer; + zip_uint16_t fname_len, ef_len; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + e = za->entry+idx; + + if (e->orig == NULL || e->orig->local_extra_fields_read) + return 0; + + if (e->orig->offset + 26 > ZIP_INT64_MAX) { + zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG); + return -1; + } + + if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + + if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) { + return -1; + } + + fname_len = _zip_buffer_get_16(buffer); + ef_len = _zip_buffer_get_16(buffer); + + if (!_zip_buffer_eof(buffer)) { + _zip_buffer_free(buffer); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + _zip_buffer_free(buffer); + + if (ef_len > 0) { + zip_extra_field_t *ef; + zip_uint8_t *ef_raw; + + if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) { + zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error); + + if (ef_raw == NULL) + return -1; + + if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) { + free(ef_raw); + return -1; + } + free(ef_raw); + + if (ef) { + ef = _zip_ef_remove_internal(ef); + e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); + } + } + + e->orig->local_extra_fields_read = 1; + + if (e->changes && e->changes->local_extra_fields_read == 0) { + e->changes->extra_fields = e->orig->extra_fields; + e->changes->local_extra_fields_read = 1; + } + + return 0; +} diff --git a/app/jni/zip_extra_field_api.c b/app/jni/zip_extra_field_api.c new file mode 100644 index 0000000..ed93944 --- /dev/null +++ b/app/jni/zip_extra_field_api.c @@ -0,0 +1,366 @@ +/* + zip_extra_field_api.c -- public extra fields API functions + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags) +{ + zip_dirent_t *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags); + return 0; +} + + +ZIP_EXTERN int +zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags) +{ + zip_dirent_t *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags); + return 0; +} + + +ZIP_EXTERN const zip_uint8_t * +zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags) +{ + static const zip_uint8_t empty[1] = { '\0' }; + + zip_dirent_t *de; + zip_extra_field_t *ef; + int i; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return NULL; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return NULL; + + i = 0; + for (ef=de->extra_fields; ef; ef=ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) { + if (i < ef_idx) { + i++; + continue; + } + + if (idp) + *idp = ef->id; + if (lenp) + *lenp = ef->size; + if (ef->size > 0) + return ef->data; + else + return empty; + } + } + + zip_error_set(&za->error, ZIP_ER_NOENT, 0); + return NULL; + +} + + +ZIP_EXTERN const zip_uint8_t * +zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags) +{ + zip_dirent_t *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return NULL; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return NULL; + + return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error); +} + + +ZIP_EXTERN zip_int16_t +zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) +{ + zip_dirent_t *de; + zip_extra_field_t *ef; + zip_uint16_t n; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return -1; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return -1; + + n = 0; + for (ef=de->extra_fields; ef; ef=ef->next) + if (ef->flags & flags & ZIP_EF_BOTH) + n++; + + return (zip_int16_t)n; +} + + +ZIP_EXTERN zip_int16_t +zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags) +{ + zip_dirent_t *de; + zip_extra_field_t *ef; + zip_uint16_t n; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return -1; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return -1; + + n = 0; + for (ef=de->extra_fields; ef; ef=ef->next) + if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) + n++; + + return (zip_int16_t)n; +} + + +ZIP_EXTERN int +zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags) +{ + zip_dirent_t *de; + zip_uint16_t ls, cs; + zip_extra_field_t *ef, *ef_prev, *ef_new; + int i, found, new_len; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (ZIP_EF_IS_INTERNAL(ef_id)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + ef = de->extra_fields; + ef_prev = NULL; + i = 0; + found = 0; + + for (; ef; ef=ef->next) { + if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) { + if (i == ef_idx) { + found = 1; + break; + } + i++; + } + ef_prev = ef; + } + + if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (flags & ZIP_EF_LOCAL) + ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL); + else + ls = 0; + if (flags & ZIP_EF_CENTRAL) + cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL); + else + cs = 0; + + new_len = ls > cs ? ls : cs; + if (found) + new_len -= ef->size + 4; + new_len += len + 4; + + if (new_len > ZIP_UINT16_MAX) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((ef_new=_zip_ef_new(ef_id, len, data, flags)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if (found) { + if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) { + ef_new->next = ef->next; + ef->next = NULL; + _zip_ef_free(ef); + if (ef_prev) + ef_prev->next = ef_new; + else + de->extra_fields = ef_new; + } + else { + ef->flags &= ~(flags & ZIP_EF_BOTH); + ef_new->next = ef->next; + ef->next = ef_new; + } + } + else if (ef_prev) { + ef_new->next = ef_prev->next; + ef_prev->next = ef_new; + } + else + de->extra_fields = ef_new; + + return 0; +} + + + +int +_zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx) +{ + zip_entry_t *e; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + e = za->entry+idx; + + if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD)) + return 0; + + if (e->orig) { + if (_zip_read_local_ef(za, idx) < 0) + return -1; + } + + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + if (e->orig && e->orig->extra_fields) { + if ((e->changes->extra_fields=_zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL) + return -1; + } + e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD; + + return 0; +} + diff --git a/app/jni/zip_fclose.c b/app/jni/zip_fclose.c new file mode 100644 index 0000000..25a201b --- /dev/null +++ b/app/jni/zip_fclose.c @@ -0,0 +1,55 @@ +/* + zip_fclose.c -- close file in zip archive + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_fclose(zip_file_t *zf) +{ + int ret; + + if (zf->src) + zip_source_free(zf->src); + + ret = 0; + if (zf->error.zip_err) + ret = zf->error.zip_err; + + zip_error_fini(&zf->error); + free(zf); + return ret; +} diff --git a/app/jni/zip_fdopen.c b/app/jni/zip_fdopen.c new file mode 100644 index 0000000..3fd771f --- /dev/null +++ b/app/jni/zip_fdopen.c @@ -0,0 +1,85 @@ +/* + zip_fdopen.c -- open read-only archive from file descriptor + Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" +#ifdef HAVE_UNISTD_H +#include +#endif + + +ZIP_EXTERN zip_t * +zip_fdopen(int fd_orig, int _flags, int *zep) +{ + int fd; + FILE *fp; + zip_t *za; + zip_source_t *src; + struct zip_error error; + + if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS|ZIP_RDONLY))) { + _zip_set_open_error(zep, NULL, ZIP_ER_INVAL); + return NULL; + } + + /* We dup() here to avoid messing with the passed in fd. + We could not restore it to the original state in case of error. */ + + if ((fd=dup(fd_orig)) < 0) { + _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); + return NULL; + } + + if ((fp=fdopen(fd, "rb")) == NULL) { + close(fd); + _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); + return NULL; + } + + zip_error_init(&error); + if ((src = zip_source_filep_create(fp, 0, -1, &error)) == NULL) { + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + if ((za = zip_open_from_source(src, _flags, &error)) == NULL) { + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + zip_error_fini(&error); + close(fd_orig); + return za; +} diff --git a/app/jni/zip_file_add.c b/app/jni/zip_file_add.c new file mode 100644 index 0000000..f9fb3be --- /dev/null +++ b/app/jni/zip_file_add.c @@ -0,0 +1,53 @@ +/* + zip_file_add.c -- add file via callback function + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +/* + NOTE: Return type is signed so we can return -1 on error. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. +*/ + +ZIP_EXTERN zip_int64_t +zip_file_add(zip_t *za, const char *name, zip_source_t *source, unsigned int flags) +{ + if (name == NULL || source == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags); +} diff --git a/app/jni/zip_file_error_clear.c b/app/jni/zip_file_error_clear.c new file mode 100644 index 0000000..be45498 --- /dev/null +++ b/app/jni/zip_file_error_clear.c @@ -0,0 +1,45 @@ +/* + zip_file_error_clear.c -- clear zip file error + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN void +zip_file_error_clear(zip_file_t *zf) +{ + if (zf == NULL) + return; + + _zip_error_clear(&zf->error); +} diff --git a/app/jni/zip_file_error_get.c b/app/jni/zip_file_error_get.c new file mode 100644 index 0000000..be764fd --- /dev/null +++ b/app/jni/zip_file_error_get.c @@ -0,0 +1,42 @@ +/* + zip_file_error_get.c -- get zip file error + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN void +zip_file_error_get(zip_file_t *zf, int *zep, int *sep) +{ + _zip_error_get(&zf->error, zep, sep); +} diff --git a/app/jni/zip_file_get_comment.c b/app/jni/zip_file_get_comment.c new file mode 100644 index 0000000..55e7dc2 --- /dev/null +++ b/app/jni/zip_file_get_comment.c @@ -0,0 +1,56 @@ +/* + zip_file_get_comment.c -- get file comment + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +/* lenp is 32 bit because converted comment can be longer than ZIP_UINT16_MAX */ + +ZIP_EXTERN const char * +zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags) +{ + zip_dirent_t *de; + zip_uint32_t len; + const zip_uint8_t *str; + + if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL) + return NULL; + + if ((str=_zip_string_get(de->comment, &len, flags, &za->error)) == NULL) + return NULL; + + if (lenp) + *lenp = len; + + return (const char *)str; +} diff --git a/app/jni/zip_file_get_external_attributes.c b/app/jni/zip_file_get_external_attributes.c new file mode 100644 index 0000000..b6526cf --- /dev/null +++ b/app/jni/zip_file_get_external_attributes.c @@ -0,0 +1,51 @@ +/* + zip_file_get_external_attributes.c -- get opsys/external attributes + Copyright (C) 2013-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +int +zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t *opsys, zip_uint32_t *attributes) +{ + zip_dirent_t *de; + + if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL) + return -1; + + if (opsys) + *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff); + + if (attributes) + *attributes = de->ext_attrib; + + return 0; +} diff --git a/app/jni/zip_file_get_offset.c b/app/jni/zip_file_get_offset.c new file mode 100644 index 0000000..16becaf --- /dev/null +++ b/app/jni/zip_file_get_offset.c @@ -0,0 +1,122 @@ +/* + zip_file_get_offset.c -- get offset of file data in archive. + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include +#include +#include + +#include "zipint.h" + + +/* _zip_file_get_offset(za, ze): + Returns the offset of the file data for entry ze. + + On error, fills in za->error and returns 0. +*/ + +zip_uint64_t +_zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) +{ + zip_uint64_t offset; + zip_int32_t size; + + if (za->entry[idx].orig == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return 0; + } + + offset = za->entry[idx].orig->offset; + + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, za->src); + return 0; + } + + /* TODO: cache? */ + if ((size=_zip_dirent_size(za->src, ZIP_EF_LOCAL, error)) < 0) + return 0; + + if (offset+(zip_uint32_t)size > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; + } + + return offset + (zip_uint32_t)size; +} + +zip_uint64_t +_zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) +{ + zip_uint64_t offset; + zip_dirent_t *entry; + + if ((offset = _zip_file_get_offset(za, index, error)) == 0) { + return 0; + } + + entry = za->entry[index].orig; + + if (offset + entry->comp_size < offset || offset + entry->comp_size > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; + } + offset += entry->comp_size; + + if (entry->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + zip_uint8_t buf[4]; + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, za->src); + return 0; + } + if (zip_source_read(za->src, buf, 4) != 4) { + _zip_error_set_from_source(error, za->src); + return 0; + } + if (memcmp(buf, DATADES_MAGIC, 4) == 0) { + offset += 4; + } + offset += 12; + if (_zip_dirent_needs_zip64(entry, 0)) { + offset += 8; + } + if (offset > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; + } + } + + return offset; +} diff --git a/app/jni/zip_file_rename.c b/app/jni/zip_file_rename.c new file mode 100644 index 0000000..4400938 --- /dev/null +++ b/app/jni/zip_file_rename.c @@ -0,0 +1,68 @@ +/* + zip_file_rename.c -- rename file in zip archive + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) +{ + const char *old_name; + int old_is_dir, new_is_dir; + + if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((old_name=zip_get_name(za, idx, 0)) == NULL) + return -1; + + new_is_dir = (name != NULL && name[strlen(name)-1] == '/'); + old_is_dir = (old_name[strlen(old_name)-1] == '/'); + + if (new_is_dir != old_is_dir) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_set_name(za, idx, name, flags); +} diff --git a/app/jni/zip_file_replace.c b/app/jni/zip_file_replace.c new file mode 100644 index 0000000..e430efa --- /dev/null +++ b/app/jni/zip_file_replace.c @@ -0,0 +1,108 @@ +/* + zip_file_replace.c -- replace file via callback function + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source, zip_flags_t flags) +{ + if (idx >= za->nentry || source == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_file_replace(za, idx, NULL, source, flags) == -1) + return -1; + + return 0; +} + + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +zip_int64_t +_zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *source, zip_flags_t flags) +{ + zip_uint64_t za_nentry_prev; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + za_nentry_prev = za->nentry; + if (idx == ZIP_UINT64_MAX) { + zip_int64_t i = -1; + + if (flags & ZIP_FL_OVERWRITE) + i = _zip_name_locate(za, name, flags, NULL); + + if (i == -1) { + /* create and use new entry, used by zip_add */ + if ((i=_zip_add_entry(za)) < 0) + return -1; + } + idx = (zip_uint64_t)i; + } + + if (name && _zip_set_name(za, idx, name, flags) != 0) { + if (za->nentry != za_nentry_prev) { + _zip_entry_finalize(za->entry+idx); + za->nentry = za_nentry_prev; + } + return -1; + } + + /* does not change any name related data, so we can do it here; + * needed for a double add of the same file name */ + _zip_unchange_data(za->entry+idx); + + if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) { + if (za->entry[idx].changes == NULL) { + if ((za->entry[idx].changes=_zip_dirent_clone(za->entry[idx].orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT; + za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD; + } + + za->entry[idx].source = source; + + return (zip_int64_t)idx; +} diff --git a/app/jni/zip_file_set_comment.c b/app/jni/zip_file_set_comment.c new file mode 100644 index 0000000..e455fbd --- /dev/null +++ b/app/jni/zip_file_set_comment.c @@ -0,0 +1,103 @@ +/* + zip_file_set_comment.c -- set comment for file in archive + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_file_set_comment(zip_t *za, zip_uint64_t idx, + const char *comment, zip_uint16_t len, zip_flags_t flags) +{ + zip_entry_t *e; + zip_string_t *cstr; + int changed; + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (len > 0 && comment == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (len > 0) { + if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + cstr->encoding = ZIP_ENCODING_UTF8_KNOWN; + } + else + cstr = NULL; + + e = za->entry+idx; + + if (e->changes) { + _zip_string_free(e->changes->comment); + e->changes->comment = NULL; + e->changes->changed &= ~ZIP_DIRENT_COMMENT; + } + + if (e->orig && e->orig->comment) + changed = !_zip_string_equal(e->orig->comment, cstr); + else + changed = (cstr != NULL); + + if (changed) { + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(cstr); + return -1; + } + } + e->changes->comment = cstr; + e->changes->changed |= ZIP_DIRENT_COMMENT; + } + else { + _zip_string_free(cstr); + if (e->changes && e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + + return 0; +} diff --git a/app/jni/zip_file_set_encryption.c b/app/jni/zip_file_set_encryption.c new file mode 100644 index 0000000..6e16135 --- /dev/null +++ b/app/jni/zip_file_set_encryption.c @@ -0,0 +1,117 @@ +/* + zip_file_set_encryption.c -- set encryption for file in archive + Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +#include +#include + +ZIP_EXTERN int +zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) +{ + zip_entry_t *e; + zip_uint16_t old_method; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (method != ZIP_EM_NONE && _zip_get_encryption_implementation(method, ZIP_CODEC_ENCODE) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return -1; + } + + e = za->entry+idx; + + old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method); + + if (method == old_method && password == NULL) { + if (e->changes) { + if (e->changes->changed & ZIP_DIRENT_PASSWORD) { + _zip_crypto_clear(e->changes->password, strlen(e->changes->password)); + free(e->changes->password); + e->changes->password = (e->orig == NULL ? NULL : e->orig->password); + } + e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD|ZIP_DIRENT_PASSWORD); + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + } + else { + char *our_password = NULL; + + if (password) { + if ((our_password = strdup(password)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + if (our_password) { + _zip_crypto_clear(our_password, strlen(our_password)); + } + free(our_password); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + e->changes->encryption_method = method; + e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD; + if (password) { + e->changes->password = our_password; + e->changes->changed |= ZIP_DIRENT_PASSWORD; + } + else { + if (e->changes->changed & ZIP_DIRENT_PASSWORD) { + _zip_crypto_clear(e->changes->password, strlen(e->changes->password)); + free(e->changes->password); + e->changes->password = e->orig ? e->orig->password : NULL; + e->changes->changed &= ~ZIP_DIRENT_PASSWORD; + } + } + } + + return 0; +} diff --git a/app/jni/zip_file_set_external_attributes.c b/app/jni/zip_file_set_external_attributes.c new file mode 100644 index 0000000..b772c31 --- /dev/null +++ b/app/jni/zip_file_set_external_attributes.c @@ -0,0 +1,83 @@ +/* + zip_file_set_external_attributes.c -- set external attributes for entry + Copyright (C) 2013-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +ZIP_EXTERN int +zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t opsys, zip_uint32_t attributes) +{ + zip_entry_t *e; + int changed; + zip_uint8_t unchanged_opsys; + zip_uint32_t unchanged_attributes; + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + e = za->entry+idx; + + unchanged_opsys = (e->orig ? (zip_uint8_t)(e->orig->version_madeby>>8) : (zip_uint8_t)ZIP_OPSYS_DEFAULT); + unchanged_attributes = e->orig ? e->orig->ext_attrib : ZIP_EXT_ATTRIB_DEFAULT; + + changed = (opsys != unchanged_opsys || attributes != unchanged_attributes); + + if (changed) { + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff)); + e->changes->ext_attrib = attributes; + e->changes->changed |= ZIP_DIRENT_ATTRIBUTES; + } + else if (e->changes) { + e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + else { + e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff)); + e->changes->ext_attrib = unchanged_attributes; + } + } + + return 0; +} diff --git a/app/jni/zip_file_set_mtime.c b/app/jni/zip_file_set_mtime.c new file mode 100644 index 0000000..0cdd31a --- /dev/null +++ b/app/jni/zip_file_set_mtime.c @@ -0,0 +1,74 @@ +/* + zip_file_set_mtime.c -- set modification time of entry. + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "zipint.h" + +ZIP_EXTERN int zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) +{ + zip_entry_t *e; + int changed; + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + e = za->entry+idx; + + changed = e->orig == NULL || mtime != e->orig->last_mod; + + if (changed) { + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + e->changes->last_mod = mtime; + e->changes->changed |= ZIP_DIRENT_LAST_MOD; + } + else { + if (e->changes) { + e->changes->changed &= ~ZIP_DIRENT_LAST_MOD; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + } + + return 0; +} diff --git a/app/jni/zip_file_strerror.c b/app/jni/zip_file_strerror.c new file mode 100644 index 0000000..8366f1e --- /dev/null +++ b/app/jni/zip_file_strerror.c @@ -0,0 +1,42 @@ +/* + zip_file_sterror.c -- get string representation of zip file error + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_file_strerror(zip_file_t *zf) +{ + return zip_error_strerror(&zf->error); +} diff --git a/app/jni/zip_filerange_crc.c b/app/jni/zip_filerange_crc.c new file mode 100644 index 0000000..775af9a --- /dev/null +++ b/app/jni/zip_filerange_crc.c @@ -0,0 +1,76 @@ +/* + zip_filerange_crc.c -- compute CRC32 for a range of a file + Copyright (C) 2008-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + + +int +_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) +{ + Bytef buf[BUFSIZE]; + zip_int64_t n; + + *crcp = crc32(0L, Z_NULL, 0); + + if (start > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return -1; + } + + if (zip_source_seek(src, (zip_int64_t)start, SEEK_SET) != 0) { + _zip_error_set_from_source(error, src); + return -1; + } + + while (len > 0) { + n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len); + if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) { + _zip_error_set_from_source(error, src); + return -1; + } + if (n == 0) { + zip_error_set(error, ZIP_ER_EOF, 0); + return -1; + } + + *crcp = crc32(*crcp, buf, (uInt)n); + + len -= (zip_uint64_t)n; + } + + return 0; +} diff --git a/app/jni/zip_fopen.c b/app/jni/zip_fopen.c new file mode 100644 index 0000000..3adb5de --- /dev/null +++ b/app/jni/zip_fopen.c @@ -0,0 +1,47 @@ +/* + zip_fopen.c -- open file in zip archive for reading + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_file_t * +zip_fopen(zip_t *za, const char *fname, zip_flags_t flags) +{ + zip_int64_t idx; + + if ((idx=zip_name_locate(za, fname, flags)) < 0) + return NULL; + + return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password); +} diff --git a/app/jni/zip_fopen_encrypted.c b/app/jni/zip_fopen_encrypted.c new file mode 100644 index 0000000..5eaf2b0 --- /dev/null +++ b/app/jni/zip_fopen_encrypted.c @@ -0,0 +1,47 @@ +/* + zip_fopen_encrypted.c -- open file for reading with password + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_file_t * +zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char *password) +{ + zip_int64_t idx; + + if ((idx=zip_name_locate(za, fname, flags)) < 0) + return NULL; + + return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password); +} diff --git a/app/jni/zip_fopen_index.c b/app/jni/zip_fopen_index.c new file mode 100644 index 0000000..0fb150b --- /dev/null +++ b/app/jni/zip_fopen_index.c @@ -0,0 +1,45 @@ +/* + zip_fopen_index.c -- open file in zip archive for reading by index + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +ZIP_EXTERN zip_file_t * +zip_fopen_index(zip_t *za, zip_uint64_t index, zip_flags_t flags) +{ + return zip_fopen_index_encrypted(za, index, flags, za->default_password); +} diff --git a/app/jni/zip_fopen_index_encrypted.c b/app/jni/zip_fopen_index_encrypted.c new file mode 100644 index 0000000..4c32e02 --- /dev/null +++ b/app/jni/zip_fopen_index_encrypted.c @@ -0,0 +1,86 @@ +/* + zip_fopen_index_encrypted.c -- open file for reading by index w/ password + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +static zip_file_t *_zip_file_new(zip_t *za); + + +ZIP_EXTERN zip_file_t * +zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, + const char *password) +{ + zip_file_t *zf; + zip_source_t *src; + + if ((src=_zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL) + return NULL; + + if (zip_source_open(src) < 0) { + _zip_error_set_from_source(&za->error, src); + zip_source_free(src); + return NULL; + } + + if ((zf=_zip_file_new(za)) == NULL) { + zip_source_free(src); + return NULL; + } + + zf->src = src; + + return zf; +} + + +static zip_file_t * +_zip_file_new(zip_t *za) +{ + zip_file_t *zf; + + if ((zf=(zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + zf->za = za; + zip_error_init(&zf->error); + zf->eof = 0; + zf->src = NULL; + + return zf; +} diff --git a/app/jni/zip_fread.c b/app/jni/zip_fread.c new file mode 100644 index 0000000..9c1cbe0 --- /dev/null +++ b/app/jni/zip_fread.c @@ -0,0 +1,63 @@ +/* + zip_fread.c -- read from file + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) +{ + zip_int64_t n; + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + if (toread > ZIP_INT64_MAX) { + zip_error_set(&zf->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((zf->eof) || (toread == 0)) + return 0; + + if ((n=zip_source_read(zf->src, outbuf, toread)) < 0) { + _zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return n; +} diff --git a/app/jni/zip_fseek.c b/app/jni/zip_fseek.c new file mode 100644 index 0000000..a16af1a --- /dev/null +++ b/app/jni/zip_fseek.c @@ -0,0 +1,54 @@ +/* + zip_fseek.c -- seek in file + Copyright (C) 2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" +#include + +ZIP_EXTERN zip_int8_t +zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) +{ + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + if (zip_source_seek(zf->src, offset, whence) < 0) { + _zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return 0; +} diff --git a/app/jni/zip_ftell.c b/app/jni/zip_ftell.c new file mode 100644 index 0000000..abbf296 --- /dev/null +++ b/app/jni/zip_ftell.c @@ -0,0 +1,56 @@ +/* + zip_ftell.c -- tell position in file + Copyright (C) 2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" +#include + +ZIP_EXTERN zip_int64_t +zip_ftell(zip_file_t *zf) +{ + zip_int64_t res; + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + res = zip_source_tell(zf->src); + if (res < 0) { + _zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return res; +} diff --git a/app/jni/zip_get_archive_comment.c b/app/jni/zip_get_archive_comment.c new file mode 100644 index 0000000..78f8ca0 --- /dev/null +++ b/app/jni/zip_get_archive_comment.c @@ -0,0 +1,59 @@ +/* + zip_get_archive_comment.c -- get archive comment + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) +{ + zip_string_t *comment; + zip_uint32_t len; + const zip_uint8_t *str; + + if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL)) + comment = za->comment_orig; + else + comment = za->comment_changes; + + if ((str=_zip_string_get(comment, &len, flags, &za->error)) == NULL) + return NULL; + + if (lenp) + *lenp = (int)len; + + return (const char *)str; +} diff --git a/app/jni/zip_get_archive_flag.c b/app/jni/zip_get_archive_flag.c new file mode 100644 index 0000000..bffe10c --- /dev/null +++ b/app/jni/zip_get_archive_flag.c @@ -0,0 +1,46 @@ +/* + zip_get_archive_flag.c -- get archive global flag + Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_get_archive_flag(zip_t *za, zip_flags_t flag, zip_flags_t flags) +{ + unsigned int fl; + + fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags; + + return (fl & flag) ? 1 : 0; +} diff --git a/app/jni/zip_get_encryption_implementation.c b/app/jni/zip_get_encryption_implementation.c new file mode 100644 index 0000000..f8af7b0 --- /dev/null +++ b/app/jni/zip_get_encryption_implementation.c @@ -0,0 +1,56 @@ +/* + zip_get_encryption_implementation.c -- get encryption implementation + Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +zip_encryption_implementation +_zip_get_encryption_implementation(zip_uint16_t em, int operation) +{ + switch (em) { + case ZIP_EM_TRAD_PKWARE: + if (operation == ZIP_CODEC_ENCODE) { + return NULL; + } + return zip_source_pkware; + + case ZIP_EM_AES_128: + case ZIP_EM_AES_192: + case ZIP_EM_AES_256: + return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode; + + default: + return NULL; + } +} diff --git a/app/jni/zip_get_file_comment.c b/app/jni/zip_get_file_comment.c new file mode 100644 index 0000000..d5f50bf --- /dev/null +++ b/app/jni/zip_get_file_comment.c @@ -0,0 +1,51 @@ +/* + zip_get_file_comment.c -- get file comment + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) +{ + zip_uint32_t len; + const char *s; + + if ((s=zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) { + if (lenp) + *lenp = (int)len; + } + + return s; +} diff --git a/app/jni/zip_get_name.c b/app/jni/zip_get_name.c new file mode 100644 index 0000000..d29e636 --- /dev/null +++ b/app/jni/zip_get_name.c @@ -0,0 +1,60 @@ +/* + zip_get_name.c -- get filename for a file in zip file + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags) +{ + return _zip_get_name(za, idx, flags, &za->error); +} + + +const char * +_zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) +{ + zip_dirent_t *de; + const zip_uint8_t *str; + + if ((de=_zip_get_dirent(za, idx, flags, error)) == NULL) + return NULL; + + if ((str=_zip_string_get(de->filename, NULL, flags, error)) == NULL) + return NULL; + + return (const char *)str; +} diff --git a/app/jni/zip_get_num_entries.c b/app/jni/zip_get_num_entries.c new file mode 100644 index 0000000..c8644a4 --- /dev/null +++ b/app/jni/zip_get_num_entries.c @@ -0,0 +1,53 @@ +/* + zip_get_num_entries.c -- get number of entries in archive + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_get_num_entries(zip_t *za, zip_flags_t flags) +{ + zip_uint64_t n; + + if (za == NULL) + return -1; + + if (flags & ZIP_FL_UNCHANGED) { + n = za->nentry; + while (n>0 && za->entry[n-1].orig == NULL) + --n; + return (zip_int64_t)n; + } + return (zip_int64_t)za->nentry; +} diff --git a/app/jni/zip_get_num_files.c b/app/jni/zip_get_num_files.c new file mode 100644 index 0000000..cf96353 --- /dev/null +++ b/app/jni/zip_get_num_files.c @@ -0,0 +1,52 @@ +/* + zip_get_num_files.c -- get number of files in archive + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" +#include + + +ZIP_EXTERN int +zip_get_num_files(zip_t *za) +{ + if (za == NULL) + return -1; + + if (za->nentry > INT_MAX) { + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + return (int)za->nentry; +} diff --git a/app/jni/zip_hash.c b/app/jni/zip_hash.c new file mode 100644 index 0000000..992e9d9 --- /dev/null +++ b/app/jni/zip_hash.c @@ -0,0 +1,420 @@ +/* + zip_hash.c -- hash table string -> uint64 + Copyright (C) 2015-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include "zipint.h" + +/* parameter for the string hash function */ +#define HASH_MULTIPLIER 33 +#define HASH_START 5381 + +/* hash table's fill ratio is kept between these by doubling/halfing its size as necessary */ +#define HASH_MAX_FILL .75 +#define HASH_MIN_FILL .01 + +/* but hash table size is kept between these */ +#define HASH_MIN_SIZE 256 +#define HASH_MAX_SIZE 0x80000000ul + +struct zip_hash_entry { + const zip_uint8_t *name; + zip_int64_t orig_index; + zip_int64_t current_index; + struct zip_hash_entry *next; + zip_uint32_t hash_value; +}; +typedef struct zip_hash_entry zip_hash_entry_t; + +struct zip_hash { + zip_uint32_t table_size; + zip_uint64_t nentries; + zip_hash_entry_t **table; +}; + + +/* free list of entries */ +static void +free_list(zip_hash_entry_t *entry) +{ + while (entry != NULL) { + zip_hash_entry_t *next = entry->next; + free(entry); + entry = next; + } +} + + +/* compute hash of string, full 32 bit value */ +static zip_uint32_t +hash_string(const zip_uint8_t *name) +{ + zip_uint64_t value = HASH_START; + + if (name == NULL) { + return 0; + } + + while (*name != 0) { + value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul); + name++; + } + + return (zip_uint32_t)value; +} + + +/* resize hash table; new_size must be a power of 2, can be larger or smaller than current size */ +static bool +hash_resize(zip_hash_t *hash, zip_uint32_t new_size, zip_error_t *error) +{ + zip_hash_entry_t **new_table; + + if (new_size == hash->table_size) { + return true; + } + + if ((new_table = (zip_hash_entry_t**)calloc(new_size, sizeof(zip_hash_entry_t *))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + if (hash->nentries > 0) { + zip_uint32_t i; + + for (i = 0; i < hash->table_size; i++) { + zip_hash_entry_t *entry = hash->table[i]; + while (entry) { + zip_hash_entry_t *next = entry->next; + + zip_uint32_t new_index = entry->hash_value % new_size; + + entry->next = new_table[new_index]; + new_table[new_index] = entry; + + entry = next; + } + } + } + + free(hash->table); + hash->table = new_table; + hash->table_size = new_size; + + return true; +} + + +static zip_uint32_t +size_for_capacity(zip_uint64_t capacity) { + double needed_size = capacity / HASH_MAX_FILL; + zip_uint32_t v; + + if (needed_size > ZIP_UINT32_MAX) { + v = ZIP_UINT32_MAX; + } + else { + v = (zip_uint32_t)needed_size; + } + + if (v > HASH_MAX_SIZE) { + return HASH_MAX_SIZE; + } + + /* From Bit Twiddling Hacks by Sean Eron Anderson + (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2). */ + + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + + return v; +} + + +zip_hash_t * +_zip_hash_new(zip_error_t *error) +{ + zip_hash_t *hash; + + if ((hash = (zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + hash->table_size = 0; + hash->nentries = 0; + hash->table = NULL; + + return hash; +} + + +void +_zip_hash_free(zip_hash_t *hash) +{ + zip_uint32_t i; + + if (hash == NULL) { + return; + } + + if (hash->table != NULL) { + for (i=0; itable_size; i++) { + if (hash->table[i] != NULL) { + free_list(hash->table[i]); + } + } + free(hash->table); + } + free(hash); +} + + +/* insert into hash, return error on existence or memory issues */ +bool +_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error) +{ + zip_uint32_t hash_value, table_index; + zip_hash_entry_t *entry; + + if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return false; + } + + if (hash->table_size == 0) { + if (!hash_resize(hash, HASH_MIN_SIZE, error)) { + return false; + } + } + + hash_value = hash_string(name); + table_index = hash_value % hash->table_size; + + for (entry = hash->table[table_index]; entry != NULL; entry = entry->next) { + if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) { + if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) { + zip_error_set(error, ZIP_ER_EXISTS, 0); + return false; + } + else { + break; + } + } + } + + if (entry == NULL) { + if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + entry->name = name; + entry->next = hash->table[table_index]; + hash->table[table_index] = entry; + entry->hash_value = hash_value; + entry->orig_index = -1; + hash->nentries++; + if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) { + if (!hash_resize(hash, hash->table_size * 2, error)) { + return false; + } + } + } + + if (flags & ZIP_FL_UNCHANGED) { + entry->orig_index = (zip_int64_t)index; + } + entry->current_index = (zip_int64_t)index; + + return true; +} + + +/* remove entry from hash, error if not found */ +bool +_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error) +{ + zip_uint32_t hash_value, index; + zip_hash_entry_t *entry, *previous; + + if (hash == NULL || name == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return false; + } + + if (hash->nentries > 0) { + hash_value = hash_string(name); + index = hash_value % hash->table_size; + previous = NULL; + entry = hash->table[index]; + while (entry) { + if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) { + if (entry->orig_index == -1) { + if (previous) { + previous->next = entry->next; + } + else { + hash->table[index] = entry->next; + } + free(entry); + hash->nentries--; + if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) { + if (!hash_resize(hash, hash->table_size / 2, error)) { + return false; + } + } + } + else { + entry->current_index = -1; + } + return true; + } + previous = entry; + entry = entry->next; + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + return false; +} + + +/* find value for entry in hash, -1 if not found */ +zip_int64_t +_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error) +{ + zip_uint32_t hash_value, index; + zip_hash_entry_t *entry; + + if (hash == NULL || name == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + if (hash->nentries > 0) { + hash_value = hash_string(name); + index = hash_value % hash->table_size; + for (entry = hash->table[index]; entry != NULL; entry = entry->next) { + if (strcmp((const char *)name, (const char *)entry->name) == 0) { + if (flags & ZIP_FL_UNCHANGED) { + if (entry->orig_index != -1) { + return entry->orig_index; + } + } + else { + if (entry->current_index != -1) { + return entry->current_index; + } + } + break; + } + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + return -1; +} + + +bool +_zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error) +{ + zip_uint32_t new_size; + + if (capacity == 0) { + return true; + } + + new_size = size_for_capacity(capacity); + + if (new_size <= hash->table_size) { + return true; + } + + if (!hash_resize(hash, new_size, error)) { + return false; + } + + return true; +} + + +bool +_zip_hash_revert(zip_hash_t *hash, zip_error_t *error) +{ + zip_uint32_t i; + zip_hash_entry_t *entry, *previous; + + for (i = 0; i < hash->table_size; i++) { + previous = NULL; + entry = hash->table[i]; + while (entry) { + if (entry->orig_index == -1) { + zip_hash_entry_t *p; + if (previous) { + previous->next = entry->next; + } + else { + hash->table[i] = entry->next; + } + p = entry; + entry = entry->next; + /* previous does not change */ + free(p); + hash->nentries--; + } + else { + entry->current_index = entry->orig_index; + previous = entry; + entry = entry->next; + } + } + } + + if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) { + zip_uint32_t new_size = hash->table_size / 2; + while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) { + new_size /= 2; + } + if (!hash_resize(hash, new_size, error)) { + return false; + } + } + + return true; +} diff --git a/app/jni/zip_io_util.c b/app/jni/zip_io_util.c new file mode 100644 index 0000000..53a5dd2 --- /dev/null +++ b/app/jni/zip_io_util.c @@ -0,0 +1,138 @@ +/* + zip_io_util.c -- I/O helper functions + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "zipint.h" + +int +_zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error) +{ + zip_int64_t n; + + if (length > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((n = zip_source_read(src, b, length)) < 0) { + _zip_error_set_from_source(error, src); + return -1; + } + + if (n < (zip_int64_t)length) { + zip_error_set(error, ZIP_ER_EOF, 0); + return -1; + } + + return 0; +} + + +zip_uint8_t * +_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error) +{ + zip_uint8_t *r; + + if (length == 0 && !nulp) { + return NULL; + } + + r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0)); + if (!r) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (buffer) { + zip_uint8_t *data = _zip_buffer_get(buffer, length); + + if (data == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(r); + return NULL; + } + memcpy(r, data, length); + } + else { + if (_zip_read(src, r, length, error) < 0) { + free(r); + return NULL; + } + } + + if (nulp) { + zip_uint8_t *o; + /* replace any in-string NUL characters with spaces */ + r[length] = 0; + for (o=r; osrc, data, length)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return -1; + } + if ((zip_uint64_t)n != length) { + zip_error_set(&za->error, ZIP_ER_WRITE, EINTR); + return -1; + } + + return 0; +} diff --git a/app/jni/zip_libzip_version.c b/app/jni/zip_libzip_version.c new file mode 100644 index 0000000..44d5612 --- /dev/null +++ b/app/jni/zip_libzip_version.c @@ -0,0 +1,42 @@ +/* + zip_libzip_version.c -- return run-time version of library + Copyright (C) 2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_libzip_version(void) +{ + return LIBZIP_VERSION; +} diff --git a/app/jni/zip_memdup.c b/app/jni/zip_memdup.c new file mode 100644 index 0000000..cc6d767 --- /dev/null +++ b/app/jni/zip_memdup.c @@ -0,0 +1,57 @@ +/* + zip_memdup.c -- internal zip function, "strdup" with len + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "zipint.h" + + +void * +_zip_memdup(const void *mem, size_t len, zip_error_t *error) +{ + void *ret; + + if (len == 0) + return NULL; + + ret = malloc(len); + if (!ret) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + memcpy(ret, mem, len); + + return ret; +} diff --git a/app/jni/zip_name_locate.c b/app/jni/zip_name_locate.c new file mode 100644 index 0000000..706093f --- /dev/null +++ b/app/jni/zip_name_locate.c @@ -0,0 +1,94 @@ +/* + zip_name_locate.c -- get index by name + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#ifdef HAVE_STRINGS_H +#include +#endif + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags) +{ + return _zip_name_locate(za, fname, flags, &za->error); +} + + +zip_int64_t +_zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *error) +{ + int (*cmp)(const char *, const char *); + const char *fn, *p; + zip_uint64_t i; + + if (za == NULL) + return -1; + + if (fname == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + if (flags & (ZIP_FL_NOCASE|ZIP_FL_NODIR|ZIP_FL_ENC_CP437)) { + /* can't use hash table */ + cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp; + + for (i=0; inentry; i++) { + fn = _zip_get_name(za, i, flags, error); + + /* newly added (partially filled) entry or error */ + if (fn == NULL) + continue; + + if (flags & ZIP_FL_NODIR) { + p = strrchr(fn, '/'); + if (p) + fn = p+1; + } + + if (cmp(fname, fn) == 0) { + _zip_error_clear(error); + return (zip_int64_t)i; + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + return -1; + } + else { + return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error); + } +} diff --git a/app/jni/zip_new.c b/app/jni/zip_new.c new file mode 100644 index 0000000..da841ff --- /dev/null +++ b/app/jni/zip_new.c @@ -0,0 +1,74 @@ +/* + zip_new.c -- create and init struct zip + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +/* _zip_new: + creates a new zipfile struct, and sets the contents to zero; returns + the new struct. */ + +zip_t * +_zip_new(zip_error_t *error) +{ + zip_t *za; + + za = (zip_t *)malloc(sizeof(struct zip)); + if (!za) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((za->names = _zip_hash_new(error)) == NULL) { + free(za); + return NULL; + } + + za->src = NULL; + za->open_flags = 0; + zip_error_init(&za->error); + za->flags = za->ch_flags = 0; + za->default_password = NULL; + za->comment_orig = za->comment_changes = NULL; + za->comment_changed = 0; + za->nentry = za->nentry_alloc = 0; + za->entry = NULL; + za->nopen_source = za->nopen_source_alloc = 0; + za->open_source = NULL; + za->progress = NULL; + + return za; +} diff --git a/app/jni/zip_open.c b/app/jni/zip_open.c new file mode 100644 index 0000000..6c62eef --- /dev/null +++ b/app/jni/zip_open.c @@ -0,0 +1,868 @@ +/* + zip_open.c -- open zip archive by name + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include +#include +#include + +#include "zipint.h" + +typedef enum { + EXISTS_ERROR = -1, + EXISTS_NOT = 0, + EXISTS_EMPTY, + EXISTS_NONEMPTY, +} exists_t; +static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error); +static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error); +static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len); +static exists_t _zip_file_exists(zip_source_t *src, zip_error_t *error); +static int _zip_headercomp(const zip_dirent_t *, const zip_dirent_t *); +static unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t); +static zip_cdir_t *_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error); +static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error); +static zip_cdir_t *_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error); + + +ZIP_EXTERN zip_t * +zip_open(const char *fn, int _flags, int *zep) +{ + zip_t *za; + zip_source_t *src; + struct zip_error error; + + zip_error_init(&error); + if ((src = zip_source_file_create(fn, 0, -1, &error)) == NULL) { + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + if ((za = zip_open_from_source(src, _flags, &error)) == NULL) { + zip_source_free(src); + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + zip_error_fini(&error); + return za; +} + + +ZIP_EXTERN zip_t * +zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) +{ + static zip_int64_t needed_support_read = -1; + static zip_int64_t needed_support_write = -1; + + unsigned int flags; + zip_int64_t supported; + exists_t exists; + + if (_flags < 0 || src == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + flags = (unsigned int)_flags; + + supported = zip_source_supports(src); + if (needed_support_read == -1) { + needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1); + needed_support_write = zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1); + } + if ((supported & needed_support_read) != needed_support_read) { + zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); + return NULL; + } + if ((supported & needed_support_write) != needed_support_write) { + flags |= ZIP_RDONLY; + } + + if ((flags & (ZIP_RDONLY|ZIP_TRUNCATE)) == (ZIP_RDONLY|ZIP_TRUNCATE)) { + zip_error_set(error, ZIP_ER_RDONLY, 0); + return NULL; + } + + exists = _zip_file_exists(src, error); + switch (exists) { + case EXISTS_ERROR: + return NULL; + + case EXISTS_NOT: + if ((flags & ZIP_CREATE) == 0) { + zip_error_set(error, ZIP_ER_NOENT, 0); + return NULL; + } + return _zip_allocate_new(src, flags, error); + + default: { + zip_t *za; + if (flags & ZIP_EXCL) { + zip_error_set(error, ZIP_ER_EXISTS, 0); + return NULL; + } + if (zip_source_open(src) < 0) { + _zip_error_set_from_source(error, src); + return NULL; + } + + if (flags & ZIP_TRUNCATE) { + za = _zip_allocate_new(src, flags, error); + } + else { + /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */ + za = _zip_open(src, flags, error); + } + + if (za == NULL) { + zip_source_close(src); + return NULL; + } + return za; + } + } +} + + +zip_t * +_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) +{ + zip_t *za; + zip_cdir_t *cdir; + struct zip_stat st; + zip_uint64_t len, idx; + + zip_stat_init(&st); + if (zip_source_stat(src, &st) < 0) { + _zip_error_set_from_source(error, src); + return NULL; + } + if ((st.valid & ZIP_STAT_SIZE) == 0) { + zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP); + return NULL; + } + len = st.size; + + /* treat empty files as empty archives */ + if (len == 0) { + if ((za=_zip_allocate_new(src, flags, error)) == NULL) { + zip_source_free(src); + return NULL; + } + + return za; + } + + if ((za=_zip_allocate_new(src, flags, error)) == NULL) { + return NULL; + } + + if ((cdir = _zip_find_central_dir(za, len)) == NULL) { + _zip_error_copy(error, &za->error); + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + + za->entry = cdir->entry; + za->nentry = cdir->nentry; + za->nentry_alloc = cdir->nentry_alloc; + za->comment_orig = cdir->comment; + + free(cdir); + + _zip_hash_reserve_capacity(za->names, za->nentry, &za->error); + + for (idx = 0; idx < za->nentry; idx++) { + const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error); + if (name == NULL) { + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + + if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) { + if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) { + _zip_error_copy(error, &za->error); + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + } + } + + za->ch_flags = za->flags; + + return za; +} + + +void +_zip_set_open_error(int *zep, const zip_error_t *err, int ze) +{ + if (err) { + ze = zip_error_code_zip(err); + if (zip_error_system_type(err) == ZIP_ET_SYS) { + errno = zip_error_code_system(err); + } + } + + if (zep) + *zep = ze; +} + + +/* _zip_readcdir: + tries to find a valid end-of-central-directory at the beginning of + buf, and then the corresponding central directory entries. + Returns a struct zip_cdir which contains the central directory + entries, or NULL if unsuccessful. */ + +static zip_cdir_t * +_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error) +{ + zip_cdir_t *cd; + zip_uint16_t comment_len; + zip_uint64_t i, left; + zip_uint64_t eocd_offset = _zip_buffer_offset(buffer); + zip_buffer_t *cd_buffer; + + if (_zip_buffer_left(buffer) < EOCDLEN) { + /* not enough bytes left for comment */ + zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + /* check for end-of-central-dir magic */ + if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 0) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) { + _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN); + cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error); + } + else { + _zip_buffer_set_offset(buffer, eocd_offset); + cd = _zip_read_eocd(buffer, buf_offset, za->flags, error); + } + + if (cd == NULL) + return NULL; + + _zip_buffer_set_offset(buffer, eocd_offset + 20); + comment_len = _zip_buffer_get_16(buffer); + + if (cd->offset + cd->size > buf_offset + eocd_offset) { + /* cdir spans past EOCD record */ + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_cdir_free(cd); + return NULL; + } + + if (comment_len || (za->open_flags & ZIP_CHECKCONS)) { + zip_uint64_t tail_len; + + _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN); + tail_len = _zip_buffer_left(buffer); + + if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_cdir_free(cd); + return NULL; + } + + if (comment_len) { + if ((cd->comment=_zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) { + _zip_cdir_free(cd); + return NULL; + } + } + } + + if (cd->offset >= buf_offset) { + zip_uint8_t *data; + /* if buffer already read in, use it */ + _zip_buffer_set_offset(buffer, cd->offset - buf_offset); + + if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_cdir_free(cd); + return NULL; + } + if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_cdir_free(cd); + return NULL; + } + } + else { + cd_buffer = NULL; + + if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, za->src); + _zip_cdir_free(cd); + return NULL; + } + + /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */ + if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + _zip_cdir_free(cd); + return NULL; + } + } + + left = (zip_uint64_t)cd->size; + i=0; + while (left > 0) { + bool grown = false; + zip_int64_t entry_size; + + if (i == cd->nentry) { + /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */ + /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */ + + if (cd->is_zip64 || left < CDENTRYSIZE) { + break; + } + + if (!_zip_cdir_grow(cd, 0x10000, error)) { + _zip_cdir_free(cd); + _zip_buffer_free(cd_buffer); + return NULL; + } + grown = true; + } + + if ((cd->entry[i].orig=_zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) { + if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) { + zip_error_set(error, ZIP_ER_INCONS, 0); + } + _zip_cdir_free(cd); + _zip_buffer_free(cd_buffer); + return NULL; + } + i++; + left -= (zip_uint64_t)entry_size; + } + + if (i != cd->nentry || left > 0) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(cd_buffer); + _zip_cdir_free(cd); + return NULL; + } + + if (za->open_flags & ZIP_CHECKCONS) { + bool ok; + + if (cd_buffer) { + ok = _zip_buffer_eof(cd_buffer); + } + else { + zip_int64_t offset = zip_source_tell(za->src); + + if (offset < 0) { + _zip_error_set_from_source(error, za->src); + _zip_cdir_free(cd); + return NULL; + } + ok = ((zip_uint64_t)offset == cd->offset + cd->size); + } + + if (!ok) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(cd_buffer); + _zip_cdir_free(cd); + return NULL; + } + } + + _zip_buffer_free(cd_buffer); + return cd; +} + + +/* _zip_checkcons: + Checks the consistency of the central directory by comparing central + directory entries with local headers and checking for plausible + file and header offsets. Returns -1 if not plausible, else the + difference between the lowest and the highest fileposition reached */ + +static zip_int64_t +_zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) +{ + zip_uint64_t i; + zip_uint64_t min, max, j; + struct zip_dirent temp; + + _zip_dirent_init(&temp); + if (cd->nentry) { + max = cd->entry[0].orig->offset; + min = cd->entry[0].orig->offset; + } + else + min = max = 0; + + for (i=0; inentry; i++) { + if (cd->entry[i].orig->offset < min) + min = cd->entry[i].orig->offset; + if (min > (zip_uint64_t)cd->offset) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE; + if (j > max) + max = j; + if (max > (zip_uint64_t)cd->offset) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + + if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, za->src); + return -1; + } + + if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) { + _zip_dirent_finalize(&temp); + return -1; + } + + if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_dirent_finalize(&temp); + return -1; + } + + cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields); + cd->entry[i].orig->local_extra_fields_read = 1; + temp.extra_fields = NULL; + + _zip_dirent_finalize(&temp); + } + + return (max-min) < ZIP_INT64_MAX ? (zip_int64_t)(max-min) : ZIP_INT64_MAX; +} + + +/* _zip_headercomp: + compares a central directory entry and a local file header + Return 0 if they are consistent, -1 if not. */ + +static int +_zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) +{ + if ((central->version_needed < local->version_needed) +#if 0 + /* some zip-files have different values in local + and global headers for the bitflags */ + || (central->bitflags != local->bitflags) +#endif + || (central->comp_method != local->comp_method) + || (central->last_mod != local->last_mod) + || !_zip_string_equal(central->filename, local->filename)) + return -1; + + if ((central->crc != local->crc) || (central->comp_size != local->comp_size) + || (central->uncomp_size != local->uncomp_size)) { + /* InfoZip stores valid values in local header even when data descriptor is used. + This is in violation of the appnote. */ + if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 + || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0)) + return -1; + } + + return 0; +} + + +static zip_t * +_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error) +{ + zip_t *za; + + if ((za = _zip_new(error)) == NULL) { + return NULL; + } + + za->src = src; + za->open_flags = flags; + if (flags & ZIP_RDONLY) { + za->flags |= ZIP_AFL_RDONLY; + za->ch_flags |= ZIP_AFL_RDONLY; + } + return za; +} + + +/* + * tests for file existence + */ +static exists_t +_zip_file_exists(zip_source_t *src, zip_error_t *error) +{ + struct zip_stat st; + + zip_stat_init(&st); + if (zip_source_stat(src, &st) != 0) { + zip_error_t *src_error = zip_source_error(src); + if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) { + return EXISTS_NOT; + } + _zip_error_copy(error, src_error); + return EXISTS_ERROR; + } + + return (st.valid & ZIP_STAT_SIZE) && st.size == 0 ? EXISTS_EMPTY : EXISTS_NONEMPTY; +} + + +static zip_cdir_t * +_zip_find_central_dir(zip_t *za, zip_uint64_t len) +{ + zip_cdir_t *cdir, *cdirnew; + zip_uint8_t *match; + zip_int64_t buf_offset; + zip_uint64_t buflen; + zip_int64_t a; + zip_int64_t best; + zip_error_t error; + zip_buffer_t *buffer; + + if (len < EOCDLEN) { + zip_error_set(&za->error, ZIP_ER_NOZIP, 0); + return NULL; + } + + buflen = (len < CDBUFSIZE ? len : CDBUFSIZE); + if (zip_source_seek(za->src, -(zip_int64_t)buflen, SEEK_END) < 0) { + zip_error_t *src_error = zip_source_error(za->src); + if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) { + /* seek before start of file on my machine */ + _zip_error_copy(&za->error, src_error); + return NULL; + } + } + if ((buf_offset = zip_source_tell(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); + return NULL; + } + + if ((buffer = _zip_buffer_new_from_source(za->src, buflen, NULL, &za->error)) == NULL) { + return NULL; + } + + best = -1; + cdir = NULL; + if (buflen >= CDBUFSIZE) { + /* EOCD64 locator is before EOCD, so leave place for it */ + _zip_buffer_set_offset(buffer, EOCD64LOCLEN); + } + zip_error_set(&error, ZIP_ER_NOZIP, 0); + + match = _zip_buffer_get(buffer, 0); + while ((match=_zip_memmem(match, _zip_buffer_left(buffer)-(EOCDLEN-4), (const unsigned char *)EOCD_MAGIC, 4)) != NULL) { + _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer))); + if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) { + if (cdir) { + if (best <= 0) { + best = _zip_checkcons(za, cdir, &error); + } + + a = _zip_checkcons(za, cdirnew, &error); + if (best < a) { + _zip_cdir_free(cdir); + cdir = cdirnew; + best = a; + } + else { + _zip_cdir_free(cdirnew); + } + } + else { + cdir = cdirnew; + if (za->open_flags & ZIP_CHECKCONS) + best = _zip_checkcons(za, cdir, &error); + else { + best = 0; + } + } + cdirnew = NULL; + } + + match++; + _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer))); + } + + _zip_buffer_free(buffer); + + if (best < 0) { + _zip_error_copy(&za->error, &error); + _zip_cdir_free(cdir); + return NULL; + } + + return cdir; +} + + +static unsigned char * +_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) +{ + const unsigned char *p; + + if ((biglen < littlelen) || (littlelen == 0)) + return NULL; + p = big-1; + while ((p=(const unsigned char *) + memchr(p+1, little[0], (size_t)(big-(p+1))+(size_t)(biglen-littlelen)+1)) != NULL) { + if (memcmp(p+1, little+1, littlelen-1)==0) + return (unsigned char *)p; + } + + return NULL; +} + + +static zip_cdir_t * +_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) +{ + zip_cdir_t *cd; + zip_uint64_t i, nentry, size, offset, eocd_offset; + + if (_zip_buffer_left(buffer) < EOCDLEN) { + zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + eocd_offset = _zip_buffer_offset(buffer); + + _zip_buffer_get(buffer, 4); /* magic already verified */ + + if (_zip_buffer_get_32(buffer) != 0) { + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + return NULL; + } + + /* number of cdir-entries on this disk */ + i = _zip_buffer_get_16(buffer); + /* number of cdir-entries */ + nentry = _zip_buffer_get_16(buffer); + + if (nentry != i) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + size = _zip_buffer_get_32(buffer); + offset = _zip_buffer_get_32(buffer); + + if (offset+size < offset) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; + } + + if (offset+size > buf_offset + eocd_offset) { + /* cdir spans past EOCD record */ + zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + if ((flags & ZIP_CHECKCONS) && offset+size != buf_offset + eocd_offset) { + zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + if ((cd=_zip_cdir_new(nentry, error)) == NULL) + return NULL; + + cd->is_zip64 = false; + cd->size = size; + cd->offset = offset; + + return cd; +} + + +static zip_cdir_t * +_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) +{ + zip_cdir_t *cd; + zip_uint64_t offset; + zip_uint8_t eocd[EOCD64LEN]; + zip_uint64_t eocd_offset; + zip_uint64_t size, nentry, i, eocdloc_offset; + bool free_buffer; + zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64; + + eocdloc_offset = _zip_buffer_offset(buffer); + + _zip_buffer_get(buffer, 4); /* magic already verified */ + + num_disks = _zip_buffer_get_16(buffer); + eocd_disk = _zip_buffer_get_16(buffer); + eocd_offset = _zip_buffer_get_64(buffer); + + if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; + } + + if (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) { + zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + if (eocd_offset >= buf_offset && eocd_offset + EOCD64LEN <= buf_offset + _zip_buffer_size(buffer)) { + _zip_buffer_set_offset(buffer, eocd_offset - buf_offset); + free_buffer = false; + } + else { + if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) { + _zip_error_set_from_source(error, src); + return NULL; + } + if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) { + return NULL; + } + free_buffer = true; + } + + if (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) { + zip_error_set(error, ZIP_ER_INCONS, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + size = _zip_buffer_get_64(buffer); + + if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) { + zip_error_set(error, ZIP_ER_INCONS, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + _zip_buffer_get(buffer, 4); /* skip version made by/needed */ + + num_disks64 = _zip_buffer_get_32(buffer); + eocd_disk64 = _zip_buffer_get_32(buffer); + + /* if eocd values are 0xffff, we have to use eocd64 values. + otherwise, if the values are not the same, it's inconsistent; + in any case, if the value is not 0, we don't support it */ + if (num_disks == 0xffff) { + num_disks = num_disks64; + } + if (eocd_disk == 0xffff) { + eocd_disk = eocd_disk64; + } + if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) { + zip_error_set(error, ZIP_ER_INCONS, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + if (num_disks != 0 || eocd_disk != 0) { + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + nentry = _zip_buffer_get_64(buffer); + i = _zip_buffer_get_64(buffer); + + if (nentry != i) { + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + size = _zip_buffer_get_64(buffer); + offset = _zip_buffer_get_64(buffer); + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + if (free_buffer) { + _zip_buffer_free(buffer); + } + + if (offset > ZIP_INT64_MAX || offset+size < offset) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; + } + if (offset+size > buf_offset + eocd_offset) { + /* cdir spans past EOCD record */ + zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + if ((flags & ZIP_CHECKCONS) && offset+size != buf_offset + eocd_offset) { + zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + + if ((cd=_zip_cdir_new(nentry, error)) == NULL) + return NULL; + + cd->is_zip64 = true; + cd->size = size; + cd->offset = offset; + + return cd; +} diff --git a/app/jni/zip_progress.c b/app/jni/zip_progress.c new file mode 100644 index 0000000..b1b6e58 --- /dev/null +++ b/app/jni/zip_progress.c @@ -0,0 +1,184 @@ +/* + zip_progress.c -- progress reporting + Copyright (C) 2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + +struct zip_progress { + zip_t *za; + zip_progress_callback callback; + void (*ud_free)(void *); + + void *ud; + + double precision; + + /* state */ + double last_update; /* last value callback function was called with */ + + double start; /* start of sub-progress section */ + double end; /* end of sub-progress section */ +}; + + +void +_zip_progress_end(zip_progress_t *progress) { + _zip_progress_update(progress, 1.0); +} + + +void +_zip_progress_free(zip_progress_t *progress) { + if (progress == NULL) { + return; + } + + if (progress->ud_free) { + progress->ud_free(progress->ud); + } + + free(progress); +} + + +zip_progress_t * +_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) { + zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress)); + + if (progress == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + progress->za = za; + progress->callback = callback; + progress->ud_free = ud_free; + progress->ud = ud; + progress->precision = precision; + + return progress; +} + + +void +_zip_progress_start(zip_progress_t *progress) { + if (progress == NULL) { + return; + } + + progress->last_update = 0.0; + progress->callback(progress->za, 0.0, progress->ud); +} + + +void +_zip_progress_subrange(zip_progress_t *progress, double start, double end) { + if (progress == NULL) { + return; + } + + progress->start = start; + progress->end = end; + + _zip_progress_update(progress, 0.0); +} + +void +_zip_progress_update(zip_progress_t *progress, double sub_current) { + double current; + + if (progress == NULL) { + return; + } + + current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start; + + if (current - progress->last_update > progress->precision) { + progress->callback(progress->za, current, progress->ud); + progress->last_update = current; + } +} + + +ZIP_EXTERN int +zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) { + zip_progress_t *progress = NULL; + + if (callback != NULL) { + if ((progress = _zip_progress_new(za, precision, callback, ud_free, ud)) == NULL) { + return -1; + } + } + + _zip_progress_free(za->progress); + za->progress = progress; + + return 0; +} + + +struct legacy_ud { + zip_progress_callback_t callback; +}; + + +static void +_zip_legacy_progress_callback(zip_t *za, double progress, void *vud) { + struct legacy_ud *ud = (struct legacy_ud *)vud; + + ud->callback(progress); +} + +ZIP_EXTERN void +zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) +{ + struct legacy_ud *ud; + + if (progress_callback == NULL) { + zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL); + } + + if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) { + return; + } + + ud->callback = progress_callback; + + if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) { + free(ud); + } +} diff --git a/app/jni/zip_random_unix.c b/app/jni/zip_random_unix.c new file mode 100644 index 0000000..2684456 --- /dev/null +++ b/app/jni/zip_random_unix.c @@ -0,0 +1,55 @@ +/* + zip_random_unix.c -- fill the user's buffer with random stuff (Unix version) + Copyright (C) 2016-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include + +bool +zip_random(zip_uint8_t *buffer, zip_uint16_t length) +{ + int fd; + + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { + return false; + } + + if (read(fd, buffer, length) != length) { + close(fd); + return false; + } + + close(fd); + return true; +} diff --git a/app/jni/zip_rename.c b/app/jni/zip_rename.c new file mode 100644 index 0000000..14e101d --- /dev/null +++ b/app/jni/zip_rename.c @@ -0,0 +1,45 @@ +/* + zip_rename.c -- rename file in zip archive + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_rename(zip_t *za, zip_uint64_t idx, const char *name) +{ + return zip_file_rename(za, idx, name, 0); +} diff --git a/app/jni/zip_replace.c b/app/jni/zip_replace.c new file mode 100644 index 0000000..eed019a --- /dev/null +++ b/app/jni/zip_replace.c @@ -0,0 +1,43 @@ +/* + zip_replace.c -- replace file via callback function + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source) +{ + return zip_file_replace(za, idx, source, 0); +} diff --git a/app/jni/zip_set_archive_comment.c b/app/jni/zip_set_archive_comment.c new file mode 100644 index 0000000..9090eec --- /dev/null +++ b/app/jni/zip_set_archive_comment.c @@ -0,0 +1,82 @@ +/* + zip_set_archive_comment.c -- set archive comment + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len) +{ + zip_string_t *cstr; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (len > 0 && comment == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (len > 0) { + if ((cstr=_zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL) + return -1; + + if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) { + _zip_string_free(cstr); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + } + else + cstr = NULL; + + _zip_string_free(za->comment_changes); + za->comment_changes = NULL; + + if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) + || (za->comment_orig == NULL && cstr == NULL))) { + _zip_string_free(cstr); + za->comment_changed = 0; + } + else { + za->comment_changes = cstr; + za->comment_changed = 1; + } + + return 0; +} diff --git a/app/jni/zip_set_archive_flag.c b/app/jni/zip_set_archive_flag.c new file mode 100644 index 0000000..2625b2e --- /dev/null +++ b/app/jni/zip_set_archive_flag.c @@ -0,0 +1,67 @@ +/* + zip_get_archive_flag.c -- set archive global flag + Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) +{ + unsigned int new_flags; + + if (value) + new_flags = za->ch_flags | flag; + else + new_flags = za->ch_flags & ~flag; + + if (new_flags == za->ch_flags) + return 0; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((flag & ZIP_AFL_RDONLY) && value + && (za->ch_flags & ZIP_AFL_RDONLY) == 0) { + if (_zip_changed(za, NULL)) { + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } + } + + za->ch_flags = new_flags; + + return 0; +} diff --git a/app/jni/zip_set_default_password.c b/app/jni/zip_set_default_password.c new file mode 100644 index 0000000..ff7e35a --- /dev/null +++ b/app/jni/zip_set_default_password.c @@ -0,0 +1,59 @@ +/* + zip_set_default_password.c -- set default password for decryption + Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_default_password(zip_t *za, const char *passwd) +{ + if (za == NULL) + return -1; + + free(za->default_password); + + if (passwd) { + if ((za->default_password=strdup(passwd)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + else + za->default_password = NULL; + + return 0; +} diff --git a/app/jni/zip_set_file_comment.c b/app/jni/zip_set_file_comment.c new file mode 100644 index 0000000..d356693 --- /dev/null +++ b/app/jni/zip_set_file_comment.c @@ -0,0 +1,49 @@ +/* + zip_set_file_comment.c -- set comment for file in archive + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_file_comment(zip_t *za, zip_uint64_t idx, const char *comment, int len) +{ + if (len < 0 || len > ZIP_UINT16_MAX) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0); +} diff --git a/app/jni/zip_set_file_compression.c b/app/jni/zip_set_file_compression.c new file mode 100644 index 0000000..5738aab --- /dev/null +++ b/app/jni/zip_set_file_compression.c @@ -0,0 +1,92 @@ +/* + zip_set_file_compression.c -- set compression for file in archive + Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_uint32_t flags) +{ + zip_entry_t *e; + zip_int32_t old_method; + + if (idx >= za->nentry || flags > 9) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (!zip_compression_method_supported(method, true)) { + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return -1; + } + + e = za->entry+idx; + + old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method); + + /* TODO: do we want to recompress if level is set? Only if it's + * different than what bit flags tell us, but those are not + * defined for all compression methods, or not directly mappable + * to levels */ + + if (method == old_method) { + if (e->changes) { + e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; + e->changes->compression_level = 0; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + } + else { + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + e->changes->comp_method = method; + e->changes->compression_level = (zip_uint16_t)flags; + e->changes->changed |= ZIP_DIRENT_COMP_METHOD; + } + + return 0; +} diff --git a/app/jni/zip_set_name.c b/app/jni/zip_set_name.c new file mode 100644 index 0000000..34b7615 --- /dev/null +++ b/app/jni/zip_set_name.c @@ -0,0 +1,158 @@ +/* + zip_set_name.c -- rename helper function + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +int +_zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) +{ + zip_entry_t *e; + zip_string_t *str; + bool same_as_orig; + zip_int64_t i; + const zip_uint8_t *old_name, *new_name; + zip_string_t *old_str; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (name && name[0] != '\0') { + /* TODO: check for string too long */ + if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = ZIP_ENCODING_UTF8_KNOWN; + } + else + str = NULL; + + /* TODO: encoding flags needed for CP437? */ + if ((i=_zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) { + _zip_string_free(str); + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + + /* no effective name change */ + if (i>=0 && (zip_uint64_t)i == idx) { + _zip_string_free(str); + return 0; + } + + e = za->entry+idx; + + if (e->orig) + same_as_orig = _zip_string_equal(e->orig->filename, str); + else + same_as_orig = false; + + if (!same_as_orig && e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(str); + return -1; + } + } + + if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) { + _zip_string_free(str); + return -1; + } + + if (e->changes) { + old_str = e->changes->filename; + } + else if (e->orig) { + old_str = e->orig->filename; + } + else { + old_str = NULL; + } + + if (old_str) { + if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) { + _zip_string_free(str); + return -1; + } + } + else { + old_name = NULL; + } + + if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) { + _zip_string_free(str); + return -1; + } + if (old_name) { + _zip_hash_delete(za->names, old_name, NULL); + } + + if (same_as_orig) { + if (e->changes) { + if (e->changes->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(e->changes->filename); + e->changes->changed &= ~ZIP_DIRENT_FILENAME; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + else { + /* TODO: what if not cloned? can that happen? */ + e->changes->filename = e->orig->filename; + } + } + } + _zip_string_free(str); + } + else { + if (e->changes->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(e->changes->filename); + } + e->changes->changed |= ZIP_DIRENT_FILENAME; + e->changes->filename = str; + } + + return 0; +} diff --git a/app/jni/zip_source_begin_write.c b/app/jni/zip_source_begin_write.c new file mode 100644 index 0000000..0459337 --- /dev/null +++ b/app/jni/zip_source_begin_write.c @@ -0,0 +1,53 @@ +/* + zip_source_begin_write.c -- start a new file for writing + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_begin_write(zip_source_t *src) +{ + if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_BEGIN_WRITE) < 0) { + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_OPEN; + + return 0; +} diff --git a/app/jni/zip_source_begin_write_cloning.c b/app/jni/zip_source_begin_write_cloning.c new file mode 100644 index 0000000..ad2cfac --- /dev/null +++ b/app/jni/zip_source_begin_write_cloning.c @@ -0,0 +1,53 @@ +/* + zip_source_begin_write_cloning.c -- clone part of file for writing + Copyright (C) 2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) +{ + if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_source_call(src, NULL, offset, ZIP_SOURCE_BEGIN_WRITE_CLONING) < 0) { + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_OPEN; + + return 0; +} diff --git a/app/jni/zip_source_buffer.c b/app/jni/zip_source_buffer.c new file mode 100644 index 0000000..86ed750 --- /dev/null +++ b/app/jni/zip_source_buffer.c @@ -0,0 +1,587 @@ +/* + zip_source_buffer.c -- create zip data source from buffer + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "zipint.h" + +#ifndef WRITE_FRAGMENT_SIZE +#define WRITE_FRAGMENT_SIZE (64*1024) +#endif + +struct buffer { + zip_buffer_fragment_t *fragments; /* fragments */ + zip_uint64_t *fragment_offsets; /* offset of each fragment from start of buffer, nfragments+1 entries */ + zip_uint64_t nfragments; /* number of allocated fragments */ + zip_uint64_t fragments_capacity; /* size of fragments (number of pointers) */ + + zip_uint64_t first_owned_fragment; /* first fragment to free data from */ + + zip_uint64_t shared_fragments; /* number of shared fragments */ + struct buffer *shared_buffer; /* buffer fragments are shared with */ + zip_uint64_t size; /* size of buffer */ + + zip_uint64_t offset; /* current offset in buffer */ + zip_uint64_t current_fragment; /* fragment current offset is in */ +}; + +typedef struct buffer buffer_t; + +struct read_data { + zip_error_t error; + time_t mtime; + buffer_t *in; + buffer_t *out; +}; + +#define buffer_capacity(buffer) ((buffer)->fragment_offsets[(buffer)->nfragments]) +#define buffer_size(buffer) ((buffer)->size) + +static buffer_t *buffer_clone(buffer_t *buffer, zip_uint64_t length, zip_error_t *error); +static zip_uint64_t buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset); +static void buffer_free(buffer_t *buffer); +static bool buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error); +static buffer_t *buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error); +static zip_int64_t buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length); +static int buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error); +static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *); + +static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t); + + +ZIP_EXTERN zip_source_t * +zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) +{ + if (za == NULL) + return NULL; + + return zip_source_buffer_create(data, len, freep, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) +{ + zip_buffer_fragment_t fragment; + + if (data == NULL && len > 0) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + fragment.data = (zip_uint8_t *)data; + fragment.length = len; + + return zip_source_buffer_fragment_create(&fragment, 1, freep, error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep) +{ + if (za == NULL) { + return NULL; + } + + return zip_source_buffer_fragment_create(fragments, nfragments, freep, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_error_t *error) +{ + struct read_data *ctx; + zip_source_t *zs; + buffer_t *buffer; + + if (fragments == NULL && nfragments > 0) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) { + return NULL; + } + + if ((ctx=(struct read_data *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + buffer_free(buffer); + return NULL; + } + + ctx->in = buffer; + ctx->out = NULL; + ctx->mtime = time(NULL); + zip_error_init(&ctx->error); + + if ((zs=zip_source_function_create(read_data, ctx, error)) == NULL) { + buffer_free(ctx->in); + free(ctx); + return NULL; + } + + return zs; +} + + +static zip_int64_t +read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) +{ + struct read_data *ctx = (struct read_data *)state; + + switch (cmd) { + case ZIP_SOURCE_BEGIN_WRITE: + if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) { + return -1; + } + ctx->out->offset = 0; + ctx->out->current_fragment = 0; + return 0; + + case ZIP_SOURCE_BEGIN_WRITE_CLONING: + if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) { + return -1; + } + ctx->out->offset = len; + ctx->out->current_fragment = ctx->out->nfragments; + return 0; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_COMMIT_WRITE: + buffer_free(ctx->in); + ctx->in = ctx->out; + ctx->out = NULL; + return 0; + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + buffer_free(ctx->in); + buffer_free(ctx->out); + free(ctx); + return 0; + + case ZIP_SOURCE_OPEN: + ctx->in->offset = 0; + ctx->in->current_fragment = 0; + return 0; + + case ZIP_SOURCE_READ: + if (len > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + return buffer_read(ctx->in, data, len); + + case ZIP_SOURCE_REMOVE: + { + buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error); + if (empty == NULL) { + return -1; + } + + buffer_free(ctx->in); + ctx->in = empty; + return 0; + } + + case ZIP_SOURCE_ROLLBACK_WRITE: + buffer_free(ctx->out); + ctx->out = NULL; + return 0; + + case ZIP_SOURCE_SEEK: + return buffer_seek(ctx->in, data, len, &ctx->error); + + case ZIP_SOURCE_SEEK_WRITE: + return buffer_seek(ctx->out, data, len, &ctx->error); + + case ZIP_SOURCE_STAT: + { + zip_stat_t *st; + + if (len < sizeof(*st)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + st = (zip_stat_t *)data; + + zip_stat_init(st); + st->mtime = ctx->mtime; + st->size = ctx->in->size; + st->comp_size = st->size; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; + st->valid = ZIP_STAT_MTIME|ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD; + + return sizeof(*st); + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1); + + case ZIP_SOURCE_TELL: + if (ctx->in->offset > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW); + return -1; + } + return (zip_int64_t)ctx->in->offset; + + + case ZIP_SOURCE_TELL_WRITE: + if (ctx->out->offset > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW); + return -1; + } + return (zip_int64_t)ctx->out->offset; + + case ZIP_SOURCE_WRITE: + if (len > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + return buffer_write(ctx->out, data, len, &ctx->error); + + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} + + +static buffer_t * +buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) { + zip_uint64_t fragment, fragment_offset, waste; + buffer_t *clone; + + if (offset == 0) { + return buffer_new(NULL, 0, 1, error); + } + + if (offset > buffer->size) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if (buffer->shared_buffer != NULL) { + zip_error_set(error, ZIP_ER_INUSE, 0); + return NULL; + } + + fragment = buffer_find_fragment(buffer, offset); + fragment_offset = offset - buffer->fragment_offsets[fragment]; + + if (fragment_offset == 0) { + fragment--; + fragment_offset = buffer->fragments[fragment].length; + } + + waste = buffer->fragments[fragment].length - fragment_offset; + if (waste > offset) { + zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); + return NULL; + } + + if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) { + return NULL; + } + + clone->fragments[clone->nfragments - 1].length = fragment_offset; + clone->fragment_offsets[clone->nfragments] = offset; + clone->size = offset; + + clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments - 1); + + buffer->shared_buffer = clone; + clone->shared_buffer = buffer; + buffer->shared_fragments = clone->nfragments; + clone->shared_fragments = fragment + 1; + + return clone; +} + + +static zip_uint64_t +buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) { + zip_uint64_t low, high, mid; + + low = 0; + high = buffer->nfragments - 1; + + while (low < high) { + mid = (high - low) / 2 + low; + if (buffer->fragment_offsets[mid] > offset) { + high = mid - 1; + } + else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) { + return mid; + } + else { + low = mid + 1; + } + } + + return low; +} + + +static void +buffer_free(buffer_t *buffer) +{ + zip_uint64_t i; + + if (buffer == NULL) { + return; + } + + if (buffer->shared_buffer != NULL) { + buffer->shared_buffer->shared_buffer = NULL; + buffer->shared_buffer->shared_fragments = 0; + + buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments); + } + + for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) { + free(buffer->fragments[i].data); + } + free(buffer->fragments); + free(buffer); +} + + +static bool +buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error) +{ + zip_buffer_fragment_t *fragments; + zip_uint64_t *offsets; + + if (capacity < buffer->fragments_capacity) { + return true; + } + + if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL + || (offsets = realloc(buffer->fragment_offsets, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) { + free(fragments); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + buffer->fragments = fragments; + buffer->fragment_offsets = offsets; + buffer->fragments_capacity = capacity; + + return true; +} + + +static buffer_t * +buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error) +{ + buffer_t *buffer; + + if ((buffer = malloc(sizeof(*buffer))) == NULL) { + return NULL; + } + + buffer->offset = 0; + buffer->first_owned_fragment = 0; + buffer->size = 0; + buffer->fragments = NULL; + buffer->fragment_offsets = NULL; + buffer->nfragments = 0; + buffer->fragments_capacity = 0; + buffer->shared_buffer = NULL; + buffer->shared_fragments = 0; + + if (nfragments == 0) { + if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) { + free(buffer); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + buffer->fragment_offsets[0] = 0; + } + else { + zip_uint64_t i, j, offset; + + if (!buffer_grow_fragments(buffer, nfragments, NULL)) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + buffer_free(buffer); + return NULL; + } + + offset = 0; + for (i = 0, j = 0; i < nfragments; i++) { + if (fragments[i].length == 0) { + continue; + } + if (fragments[i].data == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + buffer_free(buffer); + return NULL; + } + buffer->fragments[j].data = fragments[i].data; + buffer->fragments[j].length = fragments[i].length; + buffer->fragment_offsets[i] = offset; + offset += fragments[i].length; + j++; + } + buffer->nfragments = j; + buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments; + buffer->fragment_offsets[nfragments] = offset; + buffer->size = offset; + } + + return buffer; +} + +static zip_int64_t +buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) +{ + zip_uint64_t n, i, fragment_offset; + + length = ZIP_MIN(length, buffer->size - buffer->offset); + + if (length == 0) { + return 0; + } + if (length > ZIP_INT64_MAX) { + return -1; + } + + i = buffer->current_fragment; + fragment_offset = buffer->offset - buffer->fragment_offsets[i]; + n = 0; + while (n < length) { + zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset); + + memcpy(data + n, buffer->fragments[i].data + fragment_offset, left); + + if (left == buffer->fragments[i].length - fragment_offset) { + i++; + } + n += left; + fragment_offset = 0; + } + + buffer->offset += n; + buffer->current_fragment = i; + return (zip_int64_t)n; +} + + +static int +buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error) +{ + zip_int64_t new_offset = zip_source_seek_compute_offset(buffer->offset, buffer->size, data, len, error); + + if (new_offset < 0) { + return -1; + } + + buffer->offset = (zip_uint64_t)new_offset; + buffer->current_fragment = buffer_find_fragment(buffer, buffer->offset); + return 0; +} + + +static zip_int64_t +buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error) +{ + zip_uint64_t n, i, fragment_offset, capacity; + + if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + /* grow buffer if needed */ + capacity = buffer_capacity(buffer); + if (buffer->offset + length > capacity) { + zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE; + + if (needed_fragments > buffer->fragments_capacity) { + zip_uint64_t new_capacity = buffer->fragments_capacity; + + if (new_capacity == 0) { + new_capacity = 16; + } + while (new_capacity < needed_fragments) { + new_capacity *= 2; + } + + if (!buffer_grow_fragments(buffer, new_capacity, error)) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + while (buffer->nfragments < needed_fragments) { + if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE; + buffer->nfragments++; + capacity += WRITE_FRAGMENT_SIZE; + buffer->fragment_offsets[buffer->nfragments] = capacity; + } + } + + i = buffer->current_fragment; + fragment_offset = buffer->offset - buffer->fragment_offsets[i]; + n = 0; + while (n < length) { + zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset); + + memcpy(buffer->fragments[i].data + fragment_offset, data + n, left); + + if (n == buffer->fragments[i].length - fragment_offset) { + i++; + } + n += left; + fragment_offset = 0; + } + + buffer->offset += n; + buffer->current_fragment = i; + if (buffer->offset > buffer->size) { + buffer->size = buffer->offset; + } + + return (zip_int64_t)n; +} diff --git a/app/jni/zip_source_call.c b/app/jni/zip_source_call.c new file mode 100644 index 0000000..21f28bc --- /dev/null +++ b/app/jni/zip_source_call.c @@ -0,0 +1,69 @@ +/* + zip_source_call.c -- invoke callback command on zip_source + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "zipint.h" + + +zip_int64_t +_zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command) +{ + zip_int64_t ret; + + if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(command)) == 0) { + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (src->src == NULL) { + ret = src->cb.f(src->ud, data, length, command); + } + else { + ret = src->cb.l(src->src, src->ud, data, length, command); + } + + if (ret < 0) { + if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) { + int e[2]; + + if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + } + else { + zip_error_set(&src->error, e[0], e[1]); + } + } + } + + return ret; +} diff --git a/app/jni/zip_source_close.c b/app/jni/zip_source_close.c new file mode 100644 index 0000000..36bc842 --- /dev/null +++ b/app/jni/zip_source_close.c @@ -0,0 +1,58 @@ +/* + zip_source_close.c -- close zip_source (stop reading) + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +int +zip_source_close(zip_source_t *src) +{ + if (!ZIP_SOURCE_IS_OPEN_READING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + src->open_count--; + if (src->open_count == 0) { + _zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE); + + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_close(src->src) < 0) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + } + } + } + + return 0; +} diff --git a/app/jni/zip_source_commit_write.c b/app/jni/zip_source_commit_write.c new file mode 100644 index 0000000..ba77abc --- /dev/null +++ b/app/jni/zip_source_commit_write.c @@ -0,0 +1,64 @@ +/* + zip_source_commit_write.c -- commit changes to file + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_commit_write(zip_source_t *src) +{ + if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (src->open_count > 1) { + zip_error_set(&src->error, ZIP_ER_INUSE, 0); + return -1; + } + else if (ZIP_SOURCE_IS_OPEN_READING(src)) { + if (zip_source_close(src) < 0) { + return -1; + } + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_COMMIT_WRITE) < 0) { + src->write_state = ZIP_SOURCE_WRITE_FAILED; + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_CLOSED; + + return 0; +} diff --git a/app/jni/zip_source_compress.c b/app/jni/zip_source_compress.c new file mode 100644 index 0000000..0b97f93 --- /dev/null +++ b/app/jni/zip_source_compress.c @@ -0,0 +1,371 @@ +/* + zip_source_compress.c -- (de)compression routines + Copyright (C) 2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include + +#include "zipint.h" + +struct context { + zip_error_t error; + + bool end_of_input; + bool end_of_stream; + bool can_store; + bool is_stored; /* only valid if end_of_stream is true */ + bool compress; + zip_int32_t method; + + zip_uint64_t size; + zip_int64_t first_read; + zip_uint8_t buffer[BUFSIZE]; + + zip_compression_algorithm_t *algorithm; + void *ud; +}; + + +struct implementation { + zip_uint16_t method; + zip_compression_algorithm_t *compress; + zip_compression_algorithm_t *decompress; +}; + +static struct implementation implementations[] = { + { ZIP_CM_DEFLATE, &zip_algorithm_deflate_compress, &zip_algorithm_deflate_decompress }, +#if defined(HAVE_LIBBZ2) + { ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress }, +#endif +}; + +static size_t implementations_size = sizeof(implementations) / sizeof(implementations[0]); + +static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags); +static zip_int64_t compress_callback(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); +static void context_free(struct context *ctx); +static struct context *context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm); +static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t); + +static zip_compression_algorithm_t * +get_algorithm(zip_int32_t method, bool compress) { + size_t i; + zip_uint16_t real_method = ZIP_CM_ACTUAL(method); + + for (i = 0; i < implementations_size; i++) { + if (implementations[i].method == real_method) { + if (compress) { + return implementations[i].compress; + } + else { + return implementations[i].decompress; + } + } + } + + return NULL; +} + +bool +zip_compression_method_supported(zip_int32_t method, bool compress) { + if (method == ZIP_CM_STORE) { + return true; + } + return get_algorithm(method, compress) != NULL; +} + +zip_source_t * +zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, int compression_flags) { + return compression_source_new(za, src, method, true, compression_flags); +} + +zip_source_t * +zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method) { + return compression_source_new(za, src, method, false, 0); +} + + +static zip_source_t * +compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags) +{ + struct context *ctx; + zip_source_t *s2; + zip_compression_algorithm_t *algorithm = NULL; + + if (src == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((algorithm = get_algorithm(method, compress)) == NULL) { + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return NULL; + } + + if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((s2 = zip_source_layered(za, src, compress_callback, ctx)) == NULL) { + context_free(ctx); + return NULL; + } + + return s2; +} + + +static struct context * +context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm) { + struct context *ctx; + + if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + zip_error_init(&ctx->error); + ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false; + ctx->algorithm = algorithm; + ctx->method = method; + ctx->compress = compress; + ctx->end_of_input = false; + ctx->end_of_stream = false; + ctx->is_stored = false; + + if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) { + zip_error_fini(&ctx->error); + free(ctx); + return NULL; + } + + return ctx; +} + + +static void +context_free(struct context *ctx) { + if (ctx == NULL) { + return; + } + + ctx->algorithm->deallocate(ctx->ud); + zip_error_fini(&ctx->error); + + free(ctx); +} + + +static zip_int64_t +compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t len) +{ + zip_compression_status_t ret; + bool end; + zip_int64_t n; + zip_uint64_t out_offset; + zip_uint64_t out_len; + + if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) { + return -1; + } + + if (len == 0 || ctx->end_of_stream) { + return 0; + } + + out_offset = 0; + + end = false; + while (!end && out_offset < len) { + out_len = len - out_offset; + ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len); + + if (ret != ZIP_COMPRESSION_ERROR) { + out_offset += out_len; + } + + switch (ret) { + case ZIP_COMPRESSION_END: + ctx->end_of_stream = true; + + if (!ctx->end_of_input) { + /* TODO: garbage after stream, or compression ended before all data read */ + } + + if (ctx->first_read < 0) { + /* we got end of processed stream before reading any input data */ + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + end = true; + break; + } + if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) { + ctx->is_stored = true; + ctx->size = (zip_uint64_t)ctx->first_read; + memcpy(data, ctx->buffer, ctx->size); + return (zip_int64_t)ctx->size; + } + end = true; + break; + + case ZIP_COMPRESSION_OK: + break; + + case ZIP_COMPRESSION_NEED_DATA: + if (ctx->end_of_input) { + /* TODO: error: stream not ended, but no more input */ + end = true; + break; + } + + if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { + _zip_error_set_from_source(&ctx->error, src); + end = true; + break; + } + else if (n == 0) { + ctx->end_of_input = true; + ctx->algorithm->end_of_input(ctx->ud); + if (ctx->first_read < 0) { + ctx->first_read = 0; + } + } + else { + if (ctx->first_read >= 0) { + /* we overwrote a previously filled ctx->buffer */ + ctx->can_store = false; + } + else { + ctx->first_read = n; + } + + ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n); + } + break; + + case ZIP_COMPRESSION_ERROR: + /* error set by algorithm */ + if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + } + end = true; + break; + } + } + + if (out_offset > 0) { + ctx->can_store = false; + ctx->size += out_offset; + return (zip_int64_t)out_offset; + } + + return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; +} + + +static zip_int64_t +compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) +{ + struct context *ctx; + + ctx = (struct context *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->size = 0; + ctx->end_of_input = false; + ctx->end_of_stream = false; + ctx->is_stored = false; + ctx->first_read = -1; + + if (!ctx->algorithm->start(ctx->ud)) { + return -1; + } + + return 0; + + case ZIP_SOURCE_READ: + return compress_read(src, ctx, data, len); + + case ZIP_SOURCE_CLOSE: + if (!ctx->algorithm->end(ctx->ud)) { + return -1; + } + return 0; + + case ZIP_SOURCE_STAT: + { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + if (ctx->compress) { + if (ctx->end_of_stream) { + st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method); + st->comp_size = ctx->size; + st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD; + } + else { + st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD); + } + } + else { + st->comp_method = ZIP_CM_STORE; + st->valid |= ZIP_STAT_COMP_METHOD; + if (ctx->end_of_stream) { + st->size = ctx->size; + st->valid |= ZIP_STAT_SIZE; + } + else { + st->valid &= ~ZIP_STAT_SIZE; + } + } + } + return 0; + + case ZIP_SOURCE_GET_COMPRESSION_FLAGS: + return ctx->is_stored ? 0 : ctx->algorithm->compression_flags(ctx->ud); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + context_free(ctx); + return 0; + + case ZIP_SOURCE_SUPPORTS: + return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1); + + default: + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } +} diff --git a/app/jni/zip_source_crc.c b/app/jni/zip_source_crc.c new file mode 100644 index 0000000..3c9c105 --- /dev/null +++ b/app/jni/zip_source_crc.c @@ -0,0 +1,202 @@ +/* + zip_source_crc.c -- pass-through source that calculates CRC32 and size + Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include + +#include "zipint.h" + +struct crc_context { + int validate; /* whether to check CRC on EOF and return error on mismatch */ + int crc_complete; /* whether CRC was computed for complete file */ + zip_error_t error; + zip_uint64_t size; + zip_uint64_t position; /* current reading position */ + zip_uint64_t crc_position; /* how far we've computed the CRC */ + zip_uint32_t crc; +}; + +static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); + + +zip_source_t * +zip_source_crc(zip_t *za, zip_source_t *src, int validate) +{ + struct crc_context *ctx; + + if (src == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx=(struct crc_context *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + zip_error_init(&ctx->error); + ctx->validate = validate; + ctx->crc_complete = 0; + ctx->crc_position = 0; + ctx->crc = (zip_uint32_t)crc32(0, NULL, 0); + ctx->size = 0; + + return zip_source_layered(za, src, crc_read, ctx); +} + + +static zip_int64_t +crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd) +{ + struct crc_context *ctx; + zip_int64_t n; + + ctx = (struct crc_context *)_ctx; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->position = 0; + return 0; + + case ZIP_SOURCE_READ: + if ((n = zip_source_read(src, data, len)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (n == 0) { + if (ctx->crc_position == ctx->position) { + ctx->crc_complete = 1; + ctx->size = ctx->position; + + if (ctx->validate) { + struct zip_stat st; + + if (zip_source_stat(src, &st) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { + zip_error_set(&ctx->error, ZIP_ER_CRC, 0); + return -1; + } + if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { + zip_error_set(&ctx->error, ZIP_ER_INCONS, 0); + return -1; + } + } + } + } + else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) { + zip_uint64_t i, nn; + + for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) { + nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i); + + ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn); + ctx->crc_position += nn; + } + } + ctx->position += (zip_uint64_t)n; + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + if (ctx->crc_complete) { + /* TODO: Set comp_size, comp_method, encryption_method? + After all, this only works for uncompressed data. */ + st->size = ctx->size; + st->crc = ctx->crc; + st->comp_size = ctx->size; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;; + } + return 0; + } + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + free(ctx); + return 0; + + case ZIP_SOURCE_SUPPORTS: + { + zip_int64_t mask = zip_source_supports(src); + + if (mask < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1); + } + + case ZIP_SOURCE_SEEK: + { + zip_int64_t new_position; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + + if (args == NULL) { + return -1; + } + if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + ctx->position = (zip_uint64_t)new_position; + + return 0; + } + + case ZIP_SOURCE_TELL: + return (zip_int64_t)ctx->position; + + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} diff --git a/app/jni/zip_source_error.c b/app/jni/zip_source_error.c new file mode 100644 index 0000000..91e2dd6 --- /dev/null +++ b/app/jni/zip_source_error.c @@ -0,0 +1,48 @@ +/* + zip_source_error.c -- get last error from zip_source + Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +zip_error_t * +zip_source_error(zip_source_t *src) +{ + return &src->error; +} + +bool +_zip_source_had_error(zip_source_t *src) +{ + return zip_source_error(src)->zip_err != ZIP_ER_OK; +} diff --git a/app/jni/zip_source_file.c b/app/jni/zip_source_file.c new file mode 100644 index 0000000..6a10c01 --- /dev/null +++ b/app/jni/zip_source_file.c @@ -0,0 +1,63 @@ +/* + zip_source_file.c -- create data source from file + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + +#ifdef _WIN32 +#error This file is incompatible with Windows, use zip_source_win32utf8.c instead. +#error Something probably went wrong with configure/cmake. +#endif + +ZIP_EXTERN zip_source_t * +zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) +{ + if (za == NULL) + return NULL; + + return zip_source_file_create(fname, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) +{ + if (fname == NULL || length < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return _zip_source_file_or_p(fname, NULL, start, length, NULL, error); +} diff --git a/app/jni/zip_source_filep.c b/app/jni/zip_source_filep.c new file mode 100644 index 0000000..32dcdd4 --- /dev/null +++ b/app/jni/zip_source_filep.c @@ -0,0 +1,606 @@ +/* + zip_source_filep.c -- create data source from FILE * + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include + +#include "zipint.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_CLONEFILE +#include +#include +#endif + +#ifdef _WIN32 +/* WIN32 needs for _O_BINARY */ +#include +#endif + +/* Windows sys/types.h does not provide these */ +#ifndef S_ISREG +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif +#if defined(S_IXUSR) && defined(S_IRWXG) && defined(S_IRWXO) +#define _SAFE_MASK (S_IXUSR | S_IRWXG | S_IRWXO) +#elif defined(_S_IWRITE) +#define _SAFE_MASK (_S_IWRITE) +#else +#error do not know safe values for umask, please report this +#endif + +#ifdef _MSC_VER +/* MSVC doesn't have mode_t */ +typedef int mode_t; +#endif + +struct read_file { + zip_error_t error; /* last error information */ + zip_int64_t supports; + + /* reading */ + char *fname; /* name of file to read from */ + FILE *f; /* file to read from */ + struct zip_stat st; /* stat information passed in */ + zip_error_t stat_error; /* error returned for stat */ + zip_uint64_t start; /* start offset of data to read */ + zip_uint64_t end; /* end offset of data to read relative to start, 0 for up to EOF */ + zip_uint64_t current; /* current offset relative to start (0 is beginning of part we read) */ + + /* writing */ + char *tmpname; + FILE *fout; +}; + +static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd); +static int create_temp_output(struct read_file *ctx); +#ifdef HAVE_CLONEFILE +static zip_int64_t create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset); +#endif +static int _zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error); +static int _zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error); + + +ZIP_EXTERN zip_source_t * +zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) +{ + if (za == NULL) + return NULL; + + return zip_source_filep_create(file, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) +{ + if (file == NULL || length < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return _zip_source_file_or_p(NULL, file, start, length, NULL, error); +} + + +zip_source_t * +_zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_error_t *error) +{ + struct read_file *ctx; + zip_source_t *zs; + struct stat sb; + bool stat_valid; + + if (file == NULL && fname == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (len < 0) { + len = 0; + } + + if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->fname = NULL; + if (fname) { + if ((ctx->fname=strdup(fname)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + } + ctx->f = file; + ctx->start = start; + ctx->end = (zip_uint64_t)len; + if (st) { + memcpy(&ctx->st, st, sizeof(ctx->st)); + ctx->st.name = NULL; + ctx->st.valid &= ~ZIP_STAT_NAME; + } + else { + zip_stat_init(&ctx->st); + } + + if (ctx->end > 0) { + ctx->st.size = ctx->end; + ctx->st.valid |= ZIP_STAT_SIZE; + } + + zip_error_init(&ctx->stat_error); + + ctx->tmpname = NULL; + ctx->fout = NULL; + + zip_error_init(&ctx->error); + + ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1); + + if (ctx->fname) { + stat_valid = stat(ctx->fname, &sb) >= 0; + + if (!stat_valid) { + if (ctx->start == 0 && ctx->end == 0) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } + } + } + else { + stat_valid = fstat(fileno(ctx->f), &sb) >= 0; + } + + if (!stat_valid) { + zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno); + } + else { + if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) { + ctx->st.mtime = sb.st_mtime; + ctx->st.valid |= ZIP_STAT_MTIME; + } + if (S_ISREG(sb.st_mode)) { + ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; + + if (ctx->start + ctx->end > (zip_uint64_t)sb.st_size) { + zip_error_set(error, ZIP_ER_INVAL, 0); + free(ctx->fname); + free(ctx); + return NULL; + } + + if (ctx->end == 0) { + ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start; + ctx->st.valid |= ZIP_STAT_SIZE; + + if (ctx->fname && start == 0) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } + } + } + } + +#ifdef HAVE_CLONEFILE + if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) { + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING); + } +#endif + + if ((zs=zip_source_function_create(read_file, ctx, error)) == NULL) { + free(ctx->fname); + free(ctx); + return NULL; + } + + return zs; +} + + +static int +create_temp_output(struct read_file *ctx) +{ + char *temp; + int tfd; + mode_t mask; + FILE *tfp; + + if ((temp=(char *)malloc(strlen(ctx->fname)+8)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + sprintf(temp, "%s.XXXXXX", ctx->fname); + + mask = umask(_SAFE_MASK); + if ((tfd=mkstemp(temp)) == -1) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + umask(mask); + free(temp); + return -1; + } + umask(mask); + + if ((tfp=fdopen(tfd, "r+b")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + close(tfd); + (void)remove(temp); + free(temp); + return -1; + } + +#ifdef _WIN32 + /* + According to Pierre Joye, Windows in some environments per + default creates text files, so force binary mode. + */ + _setmode(_fileno(tfp), _O_BINARY ); +#endif + + ctx->fout = tfp; + ctx->tmpname = temp; + + return 0; +} + +#ifdef HAVE_CLONEFILE +zip_int64_t +static create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset) +{ + char *temp; + FILE *tfp; + + if (offset > ZIP_OFF_MAX) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, E2BIG); + return -1; + } + + if ((temp=(char *)malloc(strlen(ctx->fname)+8)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + sprintf(temp, "%s.XXXXXX", ctx->fname); + + if (mktemp(temp) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return -1; + } + + if (clonefile(ctx->fname, temp, 0) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return -1; + } + if ((tfp=fopen(temp, "r+b")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)remove(temp); + free(temp); + return -1; + } + if (ftruncate(fileno(tfp), (off_t)offset) < 0 + || fseeko(tfp, (off_t)offset, SEEK_SET) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)remove(temp); + free(temp); + return -1; + } + + ctx->fout = tfp; + ctx->tmpname = temp; + + return 0; +} +#endif + + +static zip_int64_t +read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) +{ + struct read_file *ctx; + char *buf; + zip_uint64_t n; + size_t i; + + ctx = (struct read_file *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_BEGIN_WRITE: + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + return create_temp_output(ctx); + +#ifdef HAVE_CLONEFILE + case ZIP_SOURCE_BEGIN_WRITE_CLONING: + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + return create_temp_output_cloning(ctx, len); +#endif + + case ZIP_SOURCE_COMMIT_WRITE: { + mode_t mask; + + if (fclose(ctx->fout) < 0) { + ctx->fout = NULL; + zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); + } + ctx->fout = NULL; + if (rename(ctx->tmpname, ctx->fname) < 0) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, errno); + return -1; + } + mask = umask(022); + umask(mask); + /* not much we can do if chmod fails except make the whole commit fail */ + (void)chmod(ctx->fname, 0666&~mask); + free(ctx->tmpname); + ctx->tmpname = NULL; + return 0; + } + + case ZIP_SOURCE_CLOSE: + if (ctx->fname) { + fclose(ctx->f); + ctx->f = NULL; + } + return 0; + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + free(ctx->fname); + free(ctx->tmpname); + if (ctx->f) + fclose(ctx->f); + free(ctx); + return 0; + + case ZIP_SOURCE_OPEN: + if (ctx->fname) { + if ((ctx->f=fopen(ctx->fname, "rb")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_OPEN, errno); + return -1; + } + } + + if (ctx->start > 0) { + if (_zip_fseek_u(ctx->f, ctx->start, SEEK_SET, &ctx->error) < 0) { + /* TODO: skip by reading */ + return -1; + } + } + ctx->current = 0; + return 0; + + case ZIP_SOURCE_READ: + if (ctx->end > 0) { + n = ctx->end - ctx->current; + if (n > len) { + n = len; + } + } + else { + n = len; + } + + if (n > SIZE_MAX) + n = SIZE_MAX; + + if ((i=fread(buf, 1, (size_t)n, ctx->f)) == 0) { + if (ferror(ctx->f)) { + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return -1; + } + } + ctx->current += i; + + return (zip_int64_t)i; + + case ZIP_SOURCE_REMOVE: + if (remove(ctx->fname) < 0) { + zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno); + return -1; + } + return 0; + + case ZIP_SOURCE_ROLLBACK_WRITE: + if (ctx->fout) { + fclose(ctx->fout); + ctx->fout = NULL; + } + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return 0; + + case ZIP_SOURCE_SEEK: { + zip_int64_t new_current; + int need_seek; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + + if (args == NULL) + return -1; + + need_seek = 1; + + switch (args->whence) { + case SEEK_SET: + new_current = args->offset; + break; + + case SEEK_END: + if (ctx->end == 0) { + if (_zip_fseek(ctx->f, args->offset, SEEK_END, &ctx->error) < 0) { + return -1; + } + if ((new_current = ftello(ctx->f)) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return -1; + } + new_current -= (zip_int64_t)ctx->start; + need_seek = 0; + } + else { + new_current = (zip_int64_t)ctx->end + args->offset; + } + break; + + case SEEK_CUR: + new_current = (zip_int64_t)ctx->current + args->offset; + break; + + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (new_current < 0 || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end) + || (zip_uint64_t)new_current + ctx->start < ctx->start) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + ctx->current = (zip_uint64_t)new_current; + + if (need_seek) { + if (_zip_fseek_u(ctx->f, ctx->current + ctx->start, SEEK_SET, &ctx->error) < 0) { + return -1; + } + } + return 0; + } + + case ZIP_SOURCE_SEEK_WRITE: { + zip_source_args_seek_t *args; + + args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + if (args == NULL) { + return -1; + } + + if (_zip_fseek(ctx->fout, args->offset, args->whence, &ctx->error) < 0) { + return -1; + } + return 0; + } + + case ZIP_SOURCE_STAT: { + if (len < sizeof(ctx->st)) + return -1; + + if (zip_error_code_zip(&ctx->stat_error) != 0) { + zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error)); + return -1; + } + + memcpy(data, &ctx->st, sizeof(ctx->st)); + return sizeof(ctx->st); + } + + case ZIP_SOURCE_SUPPORTS: + return ctx->supports; + + case ZIP_SOURCE_TELL: + return (zip_int64_t)ctx->current; + + case ZIP_SOURCE_TELL_WRITE: + { + off_t ret = ftello(ctx->fout); + + if (ret < 0) { + zip_error_set(&ctx->error, ZIP_ER_TELL, errno); + return -1; + } + return ret; + } + + case ZIP_SOURCE_WRITE: + { + size_t ret; + + clearerr(ctx->fout); + ret = fwrite(data, 1, len, ctx->fout); + if (ret != len || ferror(ctx->fout)) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); + return -1; + } + + return (zip_int64_t)ret; + } + + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} + + +static int +_zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error) +{ + if (offset > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW); + return -1; + } + return _zip_fseek(f, (zip_int64_t)offset, whence, error); +} + + +static int +_zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error) +{ + if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) { + zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW); + return -1; + } + if (fseeko(f, (off_t)offset, whence) < 0) { + zip_error_set(error, ZIP_ER_SEEK, errno); + return -1; + } + return 0; +} diff --git a/app/jni/zip_source_free.c b/app/jni/zip_source_free.c new file mode 100644 index 0000000..9070469 --- /dev/null +++ b/app/jni/zip_source_free.c @@ -0,0 +1,72 @@ +/* + zip_source_free.c -- free zip data source + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN void +zip_source_free(zip_source_t *src) +{ + if (src == NULL) + return; + + if (src->refcount > 0) { + src->refcount--; + } + if (src->refcount > 0) { + return; + } + + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + src->open_count = 1; /* force close */ + zip_source_close(src); + } + if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_source_rollback_write(src); + } + + if (src->source_archive && !src->source_closed) { + _zip_deregister_source(src->source_archive, src); + } + + (void)_zip_source_call(src, NULL, 0, ZIP_SOURCE_FREE); + + if (src->src) { + zip_source_free(src->src); + } + + free(src); +} diff --git a/app/jni/zip_source_function.c b/app/jni/zip_source_function.c new file mode 100644 index 0000000..3d4604c --- /dev/null +++ b/app/jni/zip_source_function.c @@ -0,0 +1,101 @@ +/* + zip_source_function.c -- create zip data source from callback function + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN zip_source_t * +zip_source_function(zip_t *za, zip_source_callback zcb, void *ud) +{ + if (za == NULL) { + return NULL; + } + + return zip_source_function_create(zcb, ud, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error) +{ + zip_source_t *zs; + + if ((zs=_zip_source_new(error)) == NULL) + return NULL; + + zs->cb.f = zcb; + zs->ud = ud; + + zs->supports = zcb(ud, NULL, 0, ZIP_SOURCE_SUPPORTS); + if (zs->supports < 0) { + zs->supports = ZIP_SOURCE_SUPPORTS_READABLE; + } + + return zs; +} + + +ZIP_EXTERN void +zip_source_keep(zip_source_t *src) +{ + src->refcount++; +} + + +zip_source_t * +_zip_source_new(zip_error_t *error) +{ + zip_source_t *src; + + if ((src=(zip_source_t *)malloc(sizeof(*src))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + src->src = NULL; + src->cb.f = NULL; + src->ud = NULL; + src->open_count = 0; + src->write_state = ZIP_SOURCE_WRITE_CLOSED; + src->source_closed = false; + src->source_archive = NULL; + src->refcount = 1; + zip_error_init(&src->error); + src->eof = false; + src->had_read_error = false; + + return src; +} diff --git a/app/jni/zip_source_get_compression_flags.c b/app/jni/zip_source_get_compression_flags.c new file mode 100644 index 0000000..b5bae82 --- /dev/null +++ b/app/jni/zip_source_get_compression_flags.c @@ -0,0 +1,58 @@ +/* + zip_source_get_compression_flags.c -- get compression flags for entry + Copyright (C) 2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +#define ZIP_COMPRESSION_BITFLAG_MAX 3 + +zip_int8_t +zip_source_get_compression_flags(zip_source_t *src) +{ + while (src) { + if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_COMPRESSION_FLAGS))) { + zip_int64_t ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_GET_COMPRESSION_FLAGS); + if (ret < 0) { + return -1; + } + if (ret > ZIP_COMPRESSION_BITFLAG_MAX) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + return -1; + } + return (zip_int8_t)ret; + } + src = src->src; + } + + return 0; +} diff --git a/app/jni/zip_source_is_deleted.c b/app/jni/zip_source_is_deleted.c new file mode 100644 index 0000000..e50cdd9 --- /dev/null +++ b/app/jni/zip_source_is_deleted.c @@ -0,0 +1,42 @@ +/* + zip_source_is_deleted.c -- was archive was removed? + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_is_deleted(zip_source_t *src) +{ + return src->write_state == ZIP_SOURCE_WRITE_REMOVED; +} diff --git a/app/jni/zip_source_layered.c b/app/jni/zip_source_layered.c new file mode 100644 index 0000000..94b3310 --- /dev/null +++ b/app/jni/zip_source_layered.c @@ -0,0 +1,69 @@ +/* + zip_source_layered.c -- create layered source + Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +zip_source_t * +zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb, void *ud) +{ + if (za == NULL) + return NULL; + + return zip_source_layered_create(src, cb, ud, &za->error); +} + + +zip_source_t * +zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error) +{ + zip_source_t *zs; + + if ((zs=_zip_source_new(error)) == NULL) + return NULL; + + zip_source_keep(src); + zs->src = src; + zs->cb.l = cb; + zs->ud = ud; + + zs->supports = cb(src, ud, NULL, 0, ZIP_SOURCE_SUPPORTS); + if (zs->supports < 0) { + zs->supports = ZIP_SOURCE_SUPPORTS_READABLE; + } + + return zs; +} diff --git a/app/jni/zip_source_open.c b/app/jni/zip_source_open.c new file mode 100644 index 0000000..ec01b0d --- /dev/null +++ b/app/jni/zip_source_open.c @@ -0,0 +1,76 @@ +/* + zip_source_open.c -- open zip_source (prepare for reading) + Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +ZIP_EXTERN int +zip_source_open(zip_source_t *src) +{ + if (src->source_closed) { + return -1; + } + if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { + zip_error_set(&src->error, ZIP_ER_DELETED, 0); + return -1; + } + + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) { + zip_error_set(&src->error, ZIP_ER_INUSE, 0); + return -1; + } + } + else { + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_open(src->src) < 0) { + _zip_error_set_from_source(&src->error, src->src); + return -1; + } + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_source_close(src->src); + } + return -1; + } + } + + src->eof = false; + src->had_read_error = false; + _zip_error_clear(&src->error); + src->open_count++; + + return 0; +} diff --git a/app/jni/zip_source_pkware.c b/app/jni/zip_source_pkware.c new file mode 100644 index 0000000..3957d99 --- /dev/null +++ b/app/jni/zip_source_pkware.c @@ -0,0 +1,226 @@ +/* + zip_source_pkware.c -- Traditional PKWARE de/encryption routines + Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +struct trad_pkware { + zip_error_t error; + zip_uint32_t key[3]; +}; + +#define HEADERLEN 12 +#define KEY0 305419896 +#define KEY1 591751049 +#define KEY2 878082192 + + +static void decrypt(struct trad_pkware *, zip_uint8_t *, + const zip_uint8_t *, zip_uint64_t, int); +static int decrypt_header(zip_source_t *, struct trad_pkware *); +static zip_int64_t pkware_decrypt(zip_source_t *, void *, void *, + zip_uint64_t, zip_source_cmd_t); +static void pkware_free(struct trad_pkware *); + + +zip_source_t * +zip_source_pkware(zip_t *za, zip_source_t *src, + zip_uint16_t em, int flags, const char *password) +{ + struct trad_pkware *ctx; + zip_source_t *s2; + + if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + if (flags & ZIP_CODEC_ENCODE) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + zip_error_init(&ctx->error); + + ctx->key[0] = KEY0; + ctx->key[1] = KEY1; + ctx->key[2] = KEY2; + decrypt(ctx, NULL, (const zip_uint8_t *)password, strlen(password), 1); + + if ((s2=zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) { + pkware_free(ctx); + return NULL; + } + + return s2; +} + + +static void +decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, + zip_uint64_t len, int update_only) +{ + zip_uint16_t tmp; + zip_uint64_t i; + Bytef b; + + for (i=0; ikey[2] | 2); + tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8); + b ^= (Bytef)tmp; + } + + /* store cleartext */ + if (out) + out[i] = b; + + /* update keys */ + ctx->key[0] = (zip_uint32_t)crc32(ctx->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; + ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1; + b = (Bytef)(ctx->key[1] >> 24); + ctx->key[2] = (zip_uint32_t)crc32(ctx->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; + } +} + + +static int +decrypt_header(zip_source_t *src, struct trad_pkware *ctx) +{ + zip_uint8_t header[HEADERLEN]; + struct zip_stat st; + zip_int64_t n; + unsigned short dostime, dosdate; + + if ((n=zip_source_read(src, header, HEADERLEN)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (n != HEADERLEN) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + + decrypt(ctx, header, header, HEADERLEN, 0); + + if (zip_source_stat(src, &st) < 0) { + /* stat failed, skip password validation */ + return 0; + } + + _zip_u2d_time(st.mtime, &dostime, &dosdate); + + if (header[HEADERLEN-1] != st.crc>>24 && header[HEADERLEN-1] != dostime>>8) { + zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); + return -1; + } + + return 0; +} + + +static zip_int64_t +pkware_decrypt(zip_source_t *src, void *ud, void *data, + zip_uint64_t len, zip_source_cmd_t cmd) +{ + struct trad_pkware *ctx; + zip_int64_t n; + + ctx = (struct trad_pkware *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + if (decrypt_header(src, ctx) < 0) + return -1; + return 0; + + case ZIP_SOURCE_READ: + if ((n=zip_source_read(src, data, len)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, 0); + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + /* TODO: deduce HEADERLEN from size for uncompressed */ + if (st->valid & ZIP_STAT_COMP_SIZE) + st->comp_size -= HEADERLEN; + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + pkware_free(ctx); + return 0; + + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } +} + + +static void +pkware_free(struct trad_pkware *ctx) +{ + free(ctx); +} diff --git a/app/jni/zip_source_read.c b/app/jni/zip_source_read.c new file mode 100644 index 0000000..5288bf2 --- /dev/null +++ b/app/jni/zip_source_read.c @@ -0,0 +1,88 @@ +/* + zip_source_read.c -- read data from zip_source + Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +zip_int64_t +zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) +{ + zip_uint64_t bytes_read; + zip_int64_t n; + + if (src->source_closed) { + return -1; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src) || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (src->had_read_error) { + return -1; + } + + if (_zip_source_eof(src)) { + return 0; + } + + bytes_read = 0; + while (bytes_read < len) { + if ((n = _zip_source_call(src, (zip_uint8_t *)data + bytes_read, len - bytes_read, ZIP_SOURCE_READ)) < 0) { + src->had_read_error = true; + if (bytes_read == 0) { + return -1; + } + else { + return (zip_int64_t)bytes_read; + } + } + + if (n == 0) { + src->eof = 1; + break; + } + + bytes_read += (zip_uint64_t)n; + } + + return (zip_int64_t)bytes_read; +} + + +bool +_zip_source_eof(zip_source_t *src) +{ + return src->eof; +} diff --git a/app/jni/zip_source_remove.c b/app/jni/zip_source_remove.c new file mode 100644 index 0000000..470a5ed --- /dev/null +++ b/app/jni/zip_source_remove.c @@ -0,0 +1,61 @@ +/* + zip_source_remove.c -- remove empty archive + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "zipint.h" + + +int +zip_source_remove(zip_source_t *src) +{ + if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { + return 0; + } + + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + if (zip_source_close(src) < 0) { + return -1; + } + } + if (src->write_state != ZIP_SOURCE_WRITE_CLOSED) { + zip_source_rollback_write(src); + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_REMOVE) < 0) { + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_REMOVED; + + return 0; +} diff --git a/app/jni/zip_source_rollback_write.c b/app/jni/zip_source_rollback_write.c new file mode 100644 index 0000000..c35f30f --- /dev/null +++ b/app/jni/zip_source_rollback_write.c @@ -0,0 +1,47 @@ +/* + zip_source_rollback_write.c -- discard changes + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN void +zip_source_rollback_write(zip_source_t *src) +{ + if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) { + return; + } + + _zip_source_call(src, NULL, 0, ZIP_SOURCE_ROLLBACK_WRITE); + src->write_state = ZIP_SOURCE_WRITE_CLOSED; +} diff --git a/app/jni/zip_source_seek.c b/app/jni/zip_source_seek.c new file mode 100644 index 0000000..c3f4703 --- /dev/null +++ b/app/jni/zip_source_seek.c @@ -0,0 +1,92 @@ +/* + zip_source_seek.c -- seek to offset + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence) +{ + zip_source_args_seek_t args; + + if (src->source_closed) { + return -1; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + args.offset = offset; + args.whence = whence; + + return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK) < 0 ? -1 : 0); +} + + +zip_int64_t +zip_source_seek_compute_offset(zip_uint64_t offset, zip_uint64_t length, void *data, zip_uint64_t data_length, zip_error_t *error) +{ + zip_int64_t new_offset; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, data_length, error); + + if (args == NULL) { + return -1; + } + + switch (args->whence) { + case SEEK_CUR: + new_offset = (zip_int64_t)offset + args->offset; + break; + + case SEEK_END: + new_offset = (zip_int64_t)length + args->offset; + break; + + case SEEK_SET: + new_offset = args->offset; + break; + + default: + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + if (new_offset < 0 || (zip_uint64_t)new_offset > length) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + return new_offset; +} diff --git a/app/jni/zip_source_seek_write.c b/app/jni/zip_source_seek_write.c new file mode 100644 index 0000000..6660766 --- /dev/null +++ b/app/jni/zip_source_seek_write.c @@ -0,0 +1,52 @@ +/* + zip_source_seek_write.c -- seek to offset for writing + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence) +{ + zip_source_args_seek_t args; + + if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + args.offset = offset; + args.whence = whence; + + return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK_WRITE) < 0 ? -1 : 0); +} diff --git a/app/jni/zip_source_stat.c b/app/jni/zip_source_stat.c new file mode 100644 index 0000000..864507e --- /dev/null +++ b/app/jni/zip_source_stat.c @@ -0,0 +1,63 @@ +/* + zip_source_stat.c -- get meta information from zip_source + Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_stat(zip_source_t *src, zip_stat_t *st) +{ + if (src->source_closed) { + return -1; + } + if (st == NULL) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + zip_stat_init(st); + + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_stat(src->src, st) < 0) { + _zip_error_set_from_source(&src->error, src->src); + return -1; + } + } + + if (_zip_source_call(src, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) { + return -1; + } + + return 0; +} diff --git a/app/jni/zip_source_supports.c b/app/jni/zip_source_supports.c new file mode 100644 index 0000000..c59aa1f --- /dev/null +++ b/app/jni/zip_source_supports.c @@ -0,0 +1,68 @@ +/* + zip_source_supports.c -- check for supported functions + Copyright (C) 2014-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +zip_int64_t +zip_source_supports(zip_source_t *src) +{ + return src->supports; +} + + +ZIP_EXTERN zip_int64_t +zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...) +{ + zip_int64_t bitmap; + va_list ap; + + bitmap = ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd0); + + + + va_start(ap, cmd0); + for (;;) { + int cmd = va_arg(ap, int); + if (cmd < 0) { + break; + } + bitmap |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd); + } + va_end(ap); + + return bitmap; +} diff --git a/app/jni/zip_source_tell.c b/app/jni/zip_source_tell.c new file mode 100644 index 0000000..f1c10b5 --- /dev/null +++ b/app/jni/zip_source_tell.c @@ -0,0 +1,50 @@ +/* + zip_source_tell.c -- report current offset + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_source_tell(zip_source_t *src) +{ + if (src->source_closed) { + return -1; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL); +} diff --git a/app/jni/zip_source_tell_write.c b/app/jni/zip_source_tell_write.c new file mode 100644 index 0000000..2fa1507 --- /dev/null +++ b/app/jni/zip_source_tell_write.c @@ -0,0 +1,47 @@ +/* + zip_source_tell_write.c -- report current offset for writing + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_source_tell_write(zip_source_t *src) +{ + if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL_WRITE); +} diff --git a/app/jni/zip_source_window.c b/app/jni/zip_source_window.c new file mode 100644 index 0000000..3980370 --- /dev/null +++ b/app/jni/zip_source_window.c @@ -0,0 +1,282 @@ +/* + zip_source_window.c -- return part of lower source + Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +struct window { + zip_uint64_t start; /* where in file we start reading */ + zip_uint64_t end; /* where in file we stop reading */ + + /* if not NULL, read file data for this file */ + zip_t *source_archive; + zip_uint64_t source_index; + + zip_uint64_t offset; /* offset in src for next read */ + + zip_stat_t stat; + zip_int8_t compression_flags; + zip_error_t error; + zip_int64_t supports; + bool needs_seek; +}; + +static zip_int64_t window_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); + + +zip_source_t * +zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len) +{ + return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, &za->error); +} + + +zip_source_t * +_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) +{ + struct window *ctx; + + if (src == NULL || start + length < start || (source_archive == NULL && source_index != 0)) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx=(struct window *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->start = start; + ctx->end = start + length; + zip_stat_init(&ctx->stat); + ctx->compression_flags = compression_flags; + ctx->source_archive = source_archive; + ctx->source_index = source_index; + zip_error_init(&ctx->error); + ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1)); + ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false; + + if (st) { + if (_zip_stat_merge(&ctx->stat, st, error) < 0) { + free(ctx); + return NULL; + } + } + + return zip_source_layered_create(src, window_read, ctx, error); +} + + +int +_zip_source_set_source_archive(zip_source_t *src, zip_t *za) +{ + src->source_archive = za; + return _zip_register_source(za, src); +} + + +/* called by zip_discard to avoid operating on file from closed archive */ +void +_zip_source_invalidate(zip_source_t *src) +{ + src->source_closed = 1; + + if (zip_error_code_zip(&src->error) == ZIP_ER_OK) { + zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0); + } +} + + +static zip_int64_t +window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd) +{ + struct window *ctx; + zip_int64_t ret; + zip_uint64_t n, i; + char b[8192]; + + ctx = (struct window *)_ctx; + + switch (cmd) { + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + free(ctx); + return 0; + + case ZIP_SOURCE_OPEN: + if (ctx->source_archive) { + zip_uint64_t offset; + + if ((offset = _zip_file_get_offset(ctx->source_archive, ctx->source_index, &ctx->error)) == 0) { + return -1; + } + if (ctx->end + offset < ctx->end) { + /* zip archive data claims end of data past zip64 limits */ + zip_error_set(&ctx->error, ZIP_ER_INCONS, 0); + return -1; + } + ctx->start += offset; + ctx->end += offset; + ctx->source_archive = NULL; + } + + if (!ctx->needs_seek) { + for (n=0; nstart; n+=(zip_uint64_t)ret) { + i = (ctx->start-n > sizeof(b) ? sizeof(b) : ctx->start-n); + if ((ret=zip_source_read(src, b, i)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + if (ret==0) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + } + + } + ctx->offset = ctx->start; + return 0; + + case ZIP_SOURCE_READ: + if (len > ctx->end - ctx->offset) + len = ctx->end - ctx->offset; + + if (len == 0) + return 0; + + if (ctx->needs_seek) { + if (zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + } + + if ((ret=zip_source_read(src, data, len)) < 0) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + + ctx->offset += (zip_uint64_t)ret; + + if (ret == 0) { + if (ctx->offset < ctx->end) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + } + return ret; + + case ZIP_SOURCE_SEEK: + { + zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error); + + if (new_offset < 0) { + return -1; + } + + ctx->offset = (zip_uint64_t)new_offset + ctx->start; + return 0; + } + + case ZIP_SOURCE_STAT: + { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) { + return -1; + } + return 0; + } + + case ZIP_SOURCE_GET_COMPRESSION_FLAGS: + return ctx->compression_flags; + + case ZIP_SOURCE_SUPPORTS: + return ctx->supports; + + case ZIP_SOURCE_TELL: + return (zip_int64_t)(ctx->offset - ctx->start); + + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} + + +void +_zip_deregister_source(zip_t *za, zip_source_t *src) +{ + unsigned int i; + + for (i=0; inopen_source; i++) { + if (za->open_source[i] == src) { + za->open_source[i] = za->open_source[za->nopen_source-1]; + za->nopen_source--; + break; + } + } +} + + +int +_zip_register_source(zip_t *za, zip_source_t *src) +{ + zip_source_t **open_source; + + if (za->nopen_source+1 >= za->nopen_source_alloc) { + unsigned int n; + n = za->nopen_source_alloc + 10; + open_source = (zip_source_t **)realloc(za->open_source, n*sizeof(zip_source_t *)); + if (open_source == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + za->nopen_source_alloc = n; + za->open_source = open_source; + } + + za->open_source[za->nopen_source++] = src; + + return 0; +} diff --git a/app/jni/zip_source_winzip_aes_decode.c b/app/jni/zip_source_winzip_aes_decode.c new file mode 100644 index 0000000..ddee1c8 --- /dev/null +++ b/app/jni/zip_source_winzip_aes_decode.c @@ -0,0 +1,289 @@ +/* + zip_source_winzip_aes.c -- Winzip AES de/encryption routines + Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +#include "gladman-fcrypt.h" + +#define MAX_HEADER_LENGTH (16+PWD_VER_LENGTH) +#define HMAC_LENGTH 10 + +static unsigned int salt_length[] = { 0, 8, 12, 16 }; + +struct winzip_aes { + char *password; + unsigned int mode; + + zip_uint64_t data_length; + zip_uint64_t current_position; + + fcrypt_ctx fcrypt_ctx; + zip_error_t error; +}; + + +static int decrypt_header(zip_source_t *src, struct winzip_aes *ctx); +static void winzip_aes_free(struct winzip_aes *); +static zip_int64_t winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd); +static struct winzip_aes * winzip_aes_new(unsigned int mode, const char *password); + + +zip_source_t * +zip_source_winzip_aes_decode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) +{ + zip_source_t *s2; + unsigned int mode = 0; + zip_stat_t st; + zip_uint64_t aux_length; + struct winzip_aes *ctx; + + switch (em) { + case ZIP_EM_AES_128: + mode = 1; + break; + case ZIP_EM_AES_192: + mode = 2; + break; + case ZIP_EM_AES_256: + mode = 3; + break; + } + + if (password == NULL || src == NULL || mode == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + if (flags & ZIP_CODEC_ENCODE) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + if (strlen(password) > UINT_MAX) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); /* TODO: better error code? (password too long) */ + return NULL; + } + + if (zip_source_stat(src, &st) != 0) { + _zip_error_set_from_source(&za->error, src); + return NULL; + } + + aux_length = PWD_VER_LENGTH + salt_length[mode] + HMAC_LENGTH; + + if ((st.valid & ZIP_STAT_COMP_SIZE) == 0 || st.comp_size < aux_length) { + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); + return NULL; + } + + if ((ctx = winzip_aes_new(mode, password)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->data_length = st.comp_size - aux_length; + + if ((s2 = zip_source_layered(za, src, winzip_aes_decrypt, ctx)) == NULL) { + winzip_aes_free(ctx); + return NULL; + } + + return s2; +} + + +static int +decrypt_header(zip_source_t *src, struct winzip_aes *ctx) +{ + zip_uint8_t header[MAX_HEADER_LENGTH]; + zip_uint8_t password_verification[PWD_VER_LENGTH]; + unsigned int headerlen; + zip_int64_t n; + + headerlen = PWD_VER_LENGTH + salt_length[ctx->mode]; + if ((n=zip_source_read(src, header, headerlen)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (n != headerlen) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + + if (_zip_fcrypt_init(ctx->mode, (unsigned char *)ctx->password, (unsigned int)strlen(ctx->password), header, password_verification, &ctx->fcrypt_ctx) != 0) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + if (memcmp(password_verification, header + salt_length[ctx->mode], PWD_VER_LENGTH) != 0) { + zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); + return -1; + } + return 0; +} + + +static bool +verify_hmac(zip_source_t *src, struct winzip_aes *ctx) +{ + unsigned char computed[HMAC_LENGTH], from_file[HMAC_LENGTH]; + if (zip_source_read(src, from_file, HMAC_LENGTH) < HMAC_LENGTH) { + _zip_error_set_from_source(&ctx->error, src); + return false; + } + + _zip_fcrypt_end(computed, &ctx->fcrypt_ctx); + + if (memcmp(from_file, computed, HMAC_LENGTH) != 0) { + zip_error_set(&ctx->error, ZIP_ER_CRC, 0); + return false; + } + + return true; +} + + +static zip_int64_t +winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) +{ + struct winzip_aes *ctx; + zip_int64_t n; + zip_uint64_t total, offset; + + ctx = (struct winzip_aes *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + if (decrypt_header(src, ctx) < 0) { + return -1; + } + ctx->current_position = 0; + return 0; + + case ZIP_SOURCE_READ: + if (len > ctx->data_length - ctx->current_position) { + len = ctx->data_length - ctx->current_position; + } + + if (len == 0) { + if (!verify_hmac(src, ctx)) { + return -1; + } + return 0; + } + + if ((n=zip_source_read(src, data, len)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + ctx->current_position += (zip_uint64_t)n; + + total = (zip_uint64_t)n; + for (offset = 0; offset < total; offset += ZIP_MIN(total - offset, UINT_MAX)) { + _zip_fcrypt_decrypt((zip_uint8_t *)data + offset, (unsigned int)ZIP_MIN(total - offset, UINT_MAX), &ctx->fcrypt_ctx); + } + + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size -= 12 + salt_length[ctx->mode]; + } + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + winzip_aes_free(ctx); + return 0; + + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } +} + + +static void +winzip_aes_free(struct winzip_aes *ctx) +{ + if (ctx == NULL) { + return; + } + + _zip_crypto_clear(&ctx->fcrypt_ctx, sizeof(ctx->fcrypt_ctx)); + _zip_crypto_clear(ctx->password, strlen(ctx->password)); + free(ctx->password); + zip_error_fini(&ctx->error); + free(ctx); +} + + +static struct winzip_aes * +winzip_aes_new(unsigned int mode, const char *password) { + struct winzip_aes *ctx; + + if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + + if ((ctx->password = strdup(password)) == NULL) { + free(ctx); + return NULL; + } + + ctx->mode = mode; + + zip_error_init(&ctx->error); + + return ctx; +} diff --git a/app/jni/zip_source_winzip_aes_encode.c b/app/jni/zip_source_winzip_aes_encode.c new file mode 100644 index 0000000..d2fe2c2 --- /dev/null +++ b/app/jni/zip_source_winzip_aes_encode.c @@ -0,0 +1,261 @@ +/* + zip_source_winzip_aes.c -- Winzip AES de/encryption routines + Copyright (C) 2009-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +#include "gladman-fcrypt.h" + +#define MAX_HEADER_LENGTH (16+PWD_VER_LENGTH) +#define HMAC_LENGTH 10 + +static unsigned int salt_length[] = { 0, 8, 12, 16 }; + +struct winzip_aes { + char *password; + unsigned int mode; + zip_uint16_t encryption_method; + + zip_uint8_t data[MAX_HEADER_LENGTH]; + zip_buffer_t *buffer; + + fcrypt_ctx fcrypt_ctx; + bool eof; + zip_error_t error; +}; + + +static int encrypt_header(zip_source_t *src, struct winzip_aes *ctx); +static void winzip_aes_free(struct winzip_aes *); +static zip_int64_t winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd); +static struct winzip_aes * winzip_aes_new(unsigned int mode, zip_uint16_t encryption_method, const char *password); + + +zip_source_t * +zip_source_winzip_aes_encode(zip_t *za, zip_source_t *src, zip_uint16_t encryption_method, int flags, const char *password) +{ + zip_source_t *s2; + unsigned int mode = 0; + struct winzip_aes *ctx; + + switch (encryption_method) { + case ZIP_EM_AES_128: + mode = 1; + break; + case ZIP_EM_AES_192: + mode = 2; + break; + case ZIP_EM_AES_256: + mode = 3; + break; + } + + if (password == NULL || src == NULL || mode == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (strlen(password) > UINT_MAX) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); /* TODO: better error code? (password too long) */ + return NULL; + } + + if ((ctx = winzip_aes_new(mode, encryption_method, password)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((s2 = zip_source_layered(za, src, winzip_aes_encrypt, ctx)) == NULL) { + winzip_aes_free(ctx); + return NULL; + } + + return s2; +} + + +static int +encrypt_header(zip_source_t *src, struct winzip_aes *ctx) +{ + if (!zip_random(ctx->data, (zip_uint16_t)salt_length[ctx->mode])) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if (_zip_fcrypt_init(ctx->mode, (unsigned char *)ctx->password, (unsigned int)strlen(ctx->password), ctx->data, ctx->data+salt_length[ctx->mode], &ctx->fcrypt_ctx) != 0) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if ((ctx->buffer = _zip_buffer_new(ctx->data, salt_length[ctx->mode] + PWD_VER_LENGTH)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + return 0; +} + + +static zip_int64_t +winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip_source_cmd_t cmd) +{ + struct winzip_aes *ctx; + zip_int64_t ret; + zip_uint64_t buffer_n, offset, n; + + ctx = (struct winzip_aes *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->eof = false; + if (encrypt_header(src, ctx) < 0) { + return -1; + } + return 0; + + case ZIP_SOURCE_READ: + buffer_n = 0; + + if (ctx->buffer) { + buffer_n = _zip_buffer_read(ctx->buffer, data, length); + + data = (zip_uint8_t *)data + buffer_n; + length -= buffer_n; + + if (_zip_buffer_eof(ctx->buffer)) { + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + } + } + + if (ctx->eof) { + return (zip_int64_t)buffer_n; + } + + if ((ret = zip_source_read(src, data, length)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + n = (zip_uint64_t)ret; + for (offset = 0; offset < n; offset += ZIP_MIN(n - offset, UINT_MAX)) { + _zip_fcrypt_encrypt((zip_uint8_t *)data + offset, (unsigned int)ZIP_MIN(n - offset, UINT_MAX), &ctx->fcrypt_ctx); + } + + if (n < length) { + ctx->eof = true; + _zip_fcrypt_end(ctx->data, &ctx->fcrypt_ctx); + if ((ctx->buffer = _zip_buffer_new(ctx->data, HMAC_LENGTH)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + /* TODO: return partial read? */ + return -1; + } + } + + return (zip_int64_t)(buffer_n + n); + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: + { + zip_stat_t *st; + + st = (zip_stat_t *)data; + st->encryption_method = ctx->encryption_method; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size += 12 + salt_length[ctx->mode]; + } + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, length); + + case ZIP_SOURCE_FREE: + winzip_aes_free(ctx); + return 0; + + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } +} + + +static void +winzip_aes_free(struct winzip_aes *ctx) +{ + if (ctx == NULL) { + return; + } + + _zip_crypto_clear(&ctx->fcrypt_ctx, sizeof(ctx->fcrypt_ctx)); + _zip_crypto_clear(ctx->password, strlen(ctx->password)); + free(ctx->password); + zip_error_fini(&ctx->error); + _zip_buffer_free(ctx->buffer); + free(ctx); +} + + +static struct winzip_aes * +winzip_aes_new(unsigned int mode, zip_uint16_t encryption_method, const char *password) { + struct winzip_aes *ctx; + + if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + + if ((ctx->password = strdup(password)) == NULL) { + free(ctx); + return NULL; + } + + ctx->mode = mode; + ctx->encryption_method = encryption_method; + ctx->buffer = NULL; + + zip_error_init(&ctx->error); + + ctx->eof = false; + return ctx; +} diff --git a/app/jni/zip_source_write.c b/app/jni/zip_source_write.c new file mode 100644 index 0000000..c98f567 --- /dev/null +++ b/app/jni/zip_source_write.c @@ -0,0 +1,47 @@ +/* + zip_source_write.c -- start a new file for writing + Copyright (C) 2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_source_write(zip_source_t *src, const void *data, zip_uint64_t length) +{ + if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || length > ZIP_INT64_MAX) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_source_call(src, (void *)data, length, ZIP_SOURCE_WRITE); +} diff --git a/app/jni/zip_source_zip.c b/app/jni/zip_source_zip.c new file mode 100644 index 0000000..e172ca2 --- /dev/null +++ b/app/jni/zip_source_zip.c @@ -0,0 +1,59 @@ +/* + zip_source_zip.c -- create data source from zip file + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +ZIP_EXTERN zip_source_t * +zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, + zip_flags_t flags, zip_uint64_t start, zip_int64_t len) +{ + if (len < -1) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (len == -1) + len = 0; + + if (start == 0 && len == 0) + flags |= ZIP_FL_COMPRESSED; + else + flags &= ~ZIP_FL_COMPRESSED; + + return _zip_source_zip_new(za, srcza, srcidx, flags, start, (zip_uint64_t)len, NULL); +} diff --git a/app/jni/zip_source_zip_new.c b/app/jni/zip_source_zip_new.c new file mode 100644 index 0000000..8a080e1 --- /dev/null +++ b/app/jni/zip_source_zip_new.c @@ -0,0 +1,177 @@ +/* + zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip + Copyright (C) 2012-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +zip_source_t * +_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) +{ + zip_source_t *src, *s2; + struct zip_stat st; + bool partial_data, needs_crc, needs_decrypt, needs_decompress; + + if (za == NULL) + return NULL; + + if (srcza == NULL || srcidx >= srcza->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && (ZIP_ENTRY_DATA_CHANGED(srcza->entry+srcidx) || srcza->entry[srcidx].deleted)) { + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return NULL; + } + + if (zip_stat_index(srcza, srcidx, flags|ZIP_FL_UNCHANGED, &st) < 0) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + if (flags & ZIP_FL_ENCRYPTED) + flags |= ZIP_FL_COMPRESSED; + + if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + /* overflow or past end of file */ + if ((start > 0 || len > 0) && (start + len < start || start + len > st.size)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (len == 0) { + len = st.size - start; + } + + partial_data = len < st.size; + needs_decrypt = ((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE); + needs_decompress = ((flags & ZIP_FL_COMPRESSED) == 0) && (st.comp_method != ZIP_CM_STORE); + /* when reading the whole file, check for CRC errors */ + needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && !partial_data; + + if (needs_decrypt) { + if (password == NULL) { + password = za->default_password; + } + if (password == NULL) { + zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0); + return NULL; + } + } + + if (st.comp_size == 0) { + return zip_source_buffer(za, NULL, 0, 0); + } + + if (partial_data && !needs_decrypt && !needs_decompress) { + struct zip_stat st2; + + st2.size = len; + st2.comp_size = len; + st2.comp_method = ZIP_CM_STORE; + st2.mtime = st.mtime; + st2.valid = ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_MTIME; + + if ((src = _zip_source_window_new(srcza->src, start, len, &st2, 0, srcza, srcidx, &za->error)) == NULL) { + return NULL; + } + } + else { + zip_dirent_t *de; + + if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) { + return NULL; + } + if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, (de->bitflags >> 1) & 3, srcza, srcidx, &za->error)) == NULL) { + return NULL; + } + } + + if (_zip_source_set_source_archive(src, srcza) < 0) { + zip_source_free(src); + return NULL; + } + + /* creating a layered source calls zip_keep() on the lower layer, so we free it */ + + if (needs_decrypt) { + zip_encryption_implementation enc_impl; + + if ((enc_impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + s2 = enc_impl(za, src, st.encryption_method, 0, password); + zip_source_free(src); + if (s2 == NULL) { + return NULL; + } + src = s2; + } + if (needs_decompress) { + s2 = zip_source_decompress(za, src, st.comp_method); + zip_source_free(src); + if (s2 == NULL) { + return NULL; + } + src = s2; + } + if (needs_crc) { + s2 = zip_source_crc(za, src, 1); + zip_source_free(src); + if (s2 == NULL) { + return NULL; + } + src = s2; + } + + if (partial_data && (needs_decrypt || needs_decompress)) { + s2 = zip_source_window(za, src, start, len); + zip_source_free(src); + if (s2 == NULL) { + return NULL; + } + src = s2; + } + + return src; +} diff --git a/app/jni/zip_stat.c b/app/jni/zip_stat.c new file mode 100644 index 0000000..cf8e566 --- /dev/null +++ b/app/jni/zip_stat.c @@ -0,0 +1,47 @@ +/* + zip_stat.c -- get information about file by name + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_stat(zip_t *za, const char *fname, zip_flags_t flags, zip_stat_t *st) +{ + zip_int64_t idx; + + if ((idx=zip_name_locate(za, fname, flags)) < 0) + return -1; + + return zip_stat_index(za, (zip_uint64_t)idx, flags, st); +} diff --git a/app/jni/zip_stat_index.c b/app/jni/zip_stat_index.c new file mode 100644 index 0000000..a2ef59b --- /dev/null +++ b/app/jni/zip_stat_index.c @@ -0,0 +1,77 @@ +/* + zip_stat_index.c -- get information about file by index + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, + zip_stat_t *st) +{ + const char *name; + zip_dirent_t *de; + + if ((de=_zip_get_dirent(za, index, flags, NULL)) == NULL) + return -1; + + if ((name=zip_get_name(za, index, flags)) == NULL) + return -1; + + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(za->entry+index)) { + if (zip_source_stat(za->entry[index].source, st) < 0) { + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } + } + else { + zip_stat_init(st); + + st->crc = de->crc; + st->size = de->uncomp_size; + st->mtime = de->last_mod; + st->comp_size = de->comp_size; + st->comp_method = (zip_uint16_t)de->comp_method; + st->encryption_method = de->encryption_method; + st->valid = (de->crc_valid ? ZIP_STAT_CRC : 0) | ZIP_STAT_SIZE|ZIP_STAT_MTIME + |ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD; + } + + st->index = index; + st->name = name; + st->valid |= ZIP_STAT_INDEX|ZIP_STAT_NAME; + + return 0; +} diff --git a/app/jni/zip_stat_init.c b/app/jni/zip_stat_init.c new file mode 100644 index 0000000..6b7d633 --- /dev/null +++ b/app/jni/zip_stat_init.c @@ -0,0 +1,85 @@ +/* + zip_stat_init.c -- initialize struct zip_stat. + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + + +ZIP_EXTERN void +zip_stat_init(zip_stat_t *st) +{ + st->valid = 0; + st->name = NULL; + st->index = ZIP_UINT64_MAX; + st->crc = 0; + st->mtime = (time_t)-1; + st->size = 0; + st->comp_size = 0; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; +} + + +int +_zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error) +{ + /* name is not merged, since zip_stat_t doesn't own it, and src may not be valid as long as dst */ + if (src->valid & ZIP_STAT_INDEX) { + dst->index = src->index; + } + if (src->valid & ZIP_STAT_SIZE) { + dst->size = src->size; + } + if (src->valid & ZIP_STAT_COMP_SIZE) { + dst->comp_size = src->comp_size; + } + if (src->valid & ZIP_STAT_MTIME) { + dst->mtime = src->mtime; + } + if (src->valid & ZIP_STAT_CRC) { + dst->crc = src->crc; + } + if (src->valid & ZIP_STAT_COMP_METHOD) { + dst->comp_method = src->comp_method; + } + if (src->valid & ZIP_STAT_ENCRYPTION_METHOD) { + dst->encryption_method = src->encryption_method; + } + if (src->valid & ZIP_STAT_FLAGS) { + dst->flags = src->flags; + } + dst->valid |= src->valid; + + return 0; +} diff --git a/app/jni/zip_strerror.c b/app/jni/zip_strerror.c new file mode 100644 index 0000000..98c4f6b --- /dev/null +++ b/app/jni/zip_strerror.c @@ -0,0 +1,42 @@ +/* + zip_sterror.c -- get string representation of zip error + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_strerror(zip_t *za) +{ + return zip_error_strerror(&za->error); +} diff --git a/app/jni/zip_string.c b/app/jni/zip_string.c new file mode 100644 index 0000000..307a425 --- /dev/null +++ b/app/jni/zip_string.c @@ -0,0 +1,188 @@ +/* + zip_string.c -- string handling (with encoding) + Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +zip_uint32_t +_zip_string_crc32(const zip_string_t *s) +{ + zip_uint32_t crc; + + crc = (zip_uint32_t)crc32(0L, Z_NULL, 0); + + if (s != NULL) + crc = (zip_uint32_t)crc32(crc, s->raw, s->length); + + return crc; +} + + +int +_zip_string_equal(const zip_string_t *a, const zip_string_t *b) +{ + if (a == NULL || b == NULL) + return a == b; + + if (a->length != b->length) + return 0; + + /* TODO: encoding */ + + return (memcmp(a->raw, b->raw, a->length) == 0); +} + + +void +_zip_string_free(zip_string_t *s) +{ + if (s == NULL) + return; + + free(s->raw); + free(s->converted); + free(s); +} + + +const zip_uint8_t * +_zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip_error_t *error) +{ + static const zip_uint8_t empty[1] = ""; + + if (string == NULL) { + if (lenp) + *lenp = 0; + return empty; + } + + if ((flags & ZIP_FL_ENC_RAW) == 0) { + /* start guessing */ + if (string->encoding == ZIP_ENCODING_UNKNOWN) + _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN); + + if (((flags & ZIP_FL_ENC_STRICT) + && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) + || (string->encoding == ZIP_ENCODING_CP437)) { + if (string->converted == NULL) { + if ((string->converted=_zip_cp437_to_utf8(string->raw, string->length, + &string->converted_length, error)) == NULL) + return NULL; + } + if (lenp) + *lenp = string->converted_length; + return string->converted; + } + } + + if (lenp) + *lenp = string->length; + return string->raw; +} + + +zip_uint16_t +_zip_string_length(const zip_string_t *s) +{ + if (s == NULL) + return 0; + + return s->length; +} + + +zip_string_t * +_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, zip_error_t *error) +{ + zip_string_t *s; + zip_encoding_type_t expected_encoding; + + if (length == 0) + return NULL; + + switch (flags & ZIP_FL_ENCODING_ALL) { + case ZIP_FL_ENC_GUESS: + expected_encoding = ZIP_ENCODING_UNKNOWN; + break; + case ZIP_FL_ENC_UTF_8: + expected_encoding = ZIP_ENCODING_UTF8_KNOWN; + break; + case ZIP_FL_ENC_CP437: + expected_encoding = ZIP_ENCODING_CP437; + break; + default: + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((s=(zip_string_t *)malloc(sizeof(*s))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((s->raw=(zip_uint8_t *)malloc((size_t)(length+1))) == NULL) { + free(s); + return NULL; + } + + memcpy(s->raw, raw, length); + s->raw[length] = '\0'; + s->length = length; + s->encoding = ZIP_ENCODING_UNKNOWN; + s->converted = NULL; + s->converted_length = 0; + + if (expected_encoding != ZIP_ENCODING_UNKNOWN) { + if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) { + _zip_string_free(s); + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + } + + return s; +} + + +int +_zip_string_write(zip_t *za, const zip_string_t *s) +{ + if (s == NULL) + return 0; + + return _zip_write(za, s->raw, s->length); +} diff --git a/app/jni/zip_unchange.c b/app/jni/zip_unchange.c new file mode 100644 index 0000000..4a3d642 --- /dev/null +++ b/app/jni/zip_unchange.c @@ -0,0 +1,95 @@ +/* + zip_unchange.c -- undo changes to file in zip archive + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_unchange(zip_t *za, zip_uint64_t idx) +{ + return _zip_unchange(za, idx, 0); +} + + +int +_zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates) +{ + zip_int64_t i; + const char *orig_name, *changed_name; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) { + if (za->entry[idx].orig != NULL) { + if ((orig_name=_zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) { + return -1; + } + + i = _zip_name_locate(za, orig_name, 0, NULL); + if (i >= 0 && (zip_uint64_t)i != idx) { + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + } + else { + orig_name = NULL; + } + + if ((changed_name=_zip_get_name(za, idx, 0, &za->error)) == NULL) { + return -1; + } + + if (orig_name) { + if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) { + return -1; + } + } + if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) { + _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL); + return -1; + } + } + + _zip_dirent_free(za->entry[idx].changes); + za->entry[idx].changes = NULL; + + _zip_unchange_data(za->entry+idx); + + return 0; +} diff --git a/app/jni/zip_unchange_all.c b/app/jni/zip_unchange_all.c new file mode 100644 index 0000000..885c77d --- /dev/null +++ b/app/jni/zip_unchange_all.c @@ -0,0 +1,57 @@ +/* + zip_unchange.c -- undo changes to all files in zip archive + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_unchange_all(zip_t *za) +{ + int ret; + zip_uint64_t i; + + if (!_zip_hash_revert(za->names, &za->error)) { + return -1; + } + + ret = 0; + for (i=0; inentry; i++) + ret |= _zip_unchange(za, i, 1); + + ret |= zip_unchange_archive(za); + + return ret; +} diff --git a/app/jni/zip_unchange_archive.c b/app/jni/zip_unchange_archive.c new file mode 100644 index 0000000..920255c --- /dev/null +++ b/app/jni/zip_unchange_archive.c @@ -0,0 +1,52 @@ +/* + zip_unchange_archive.c -- undo global changes to ZIP archive + Copyright (C) 2006-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_unchange_archive(zip_t *za) +{ + if (za->comment_changed) { + _zip_string_free(za->comment_changes); + za->comment_changes = NULL; + za->comment_changed = 0; + } + + za->ch_flags = za->flags; + + return 0; +} diff --git a/app/jni/zip_unchange_data.c b/app/jni/zip_unchange_data.c new file mode 100644 index 0000000..839d9a3 --- /dev/null +++ b/app/jni/zip_unchange_data.c @@ -0,0 +1,55 @@ +/* + zip_unchange_data.c -- undo helper function + Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +void +_zip_unchange_data(zip_entry_t *ze) +{ + if (ze->source) { + zip_source_free(ze->source); + ze->source = NULL; + } + + if (ze->changes != NULL && (ze->changes->changed & ZIP_DIRENT_COMP_METHOD) && ze->changes->comp_method == ZIP_CM_REPLACED_DEFAULT) { + ze->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; + if (ze->changes->changed == 0) { + _zip_dirent_free(ze->changes); + ze->changes = NULL; + } + } + + ze->deleted = 0; +} + diff --git a/app/jni/zip_utf-8.c b/app/jni/zip_utf-8.c new file mode 100644 index 0000000..f38eea0 --- /dev/null +++ b/app/jni/zip_utf-8.c @@ -0,0 +1,249 @@ +/* + zip_utf-8.c -- UTF-8 support functions for libzip + Copyright (C) 2011-2014 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +#include + + +static const zip_uint16_t _cp437_to_unicode[256] = { + /* 0x00 - 0x0F */ + 0x2007, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, + 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C, + + /* 0x10 - 0x1F */ + 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8, + 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC, + + /* 0x20 - 0x2F */ + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + + /* 0x30 - 0x3F */ + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + + /* 0x40 - 0x4F */ + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + + /* 0x50 - 0x5F */ + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + + /* 0x60 - 0x6F */ + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + + /* 0x70 - 0x7F */ + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x2302, + + /* 0x80 - 0x8F */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + + /* 0x90 - 0x9F */ + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + + /* 0xA0 - 0xAF */ + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + + /* 0xB0 - 0xBF */ + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + + /* 0xC0 - 0xCF */ + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + + /* 0xD0 - 0xDF */ + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + + /* 0xE0 - 0xEF */ + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, + 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + + /* 0xF0 - 0xFF */ + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#define UTF_8_LEN_2_MASK 0xe0 +#define UTF_8_LEN_2_MATCH 0xc0 +#define UTF_8_LEN_3_MASK 0xf0 +#define UTF_8_LEN_3_MATCH 0xe0 +#define UTF_8_LEN_4_MASK 0xf8 +#define UTF_8_LEN_4_MATCH 0xf0 +#define UTF_8_CONTINUE_MASK 0xc0 +#define UTF_8_CONTINUE_MATCH 0x80 + + +zip_encoding_type_t +_zip_guess_encoding(zip_string_t *str, zip_encoding_type_t expected_encoding) +{ + zip_encoding_type_t enc; + const zip_uint8_t *name; + zip_uint32_t i, j, ulen; + + if (str == NULL) + return ZIP_ENCODING_ASCII; + + name = str->raw; + + if (str->encoding != ZIP_ENCODING_UNKNOWN) + enc = str->encoding; + else { + enc = ZIP_ENCODING_ASCII; + for (i=0; ilength; i++) { + if ((name[i] > 31 && name[i] < 128) || name[i] == '\r' || name[i] == '\n' || name[i] == '\t') + continue; + + enc = ZIP_ENCODING_UTF8_GUESSED; + if ((name[i] & UTF_8_LEN_2_MASK) == UTF_8_LEN_2_MATCH) + ulen = 1; + else if ((name[i] & UTF_8_LEN_3_MASK) == UTF_8_LEN_3_MATCH) + ulen = 2; + else if ((name[i] & UTF_8_LEN_4_MASK) == UTF_8_LEN_4_MATCH) + ulen = 3; + else { + enc = ZIP_ENCODING_CP437; + break; + } + + if (i + ulen >= str->length) { + enc = ZIP_ENCODING_CP437; + break; + } + + for (j=1; j<=ulen; j++) { + if ((name[i+j] & UTF_8_CONTINUE_MASK) != UTF_8_CONTINUE_MATCH) { + enc = ZIP_ENCODING_CP437; + goto done; + } + } + i += ulen; + } + } + +done: + str->encoding = enc; + + if (expected_encoding != ZIP_ENCODING_UNKNOWN) { + if (expected_encoding == ZIP_ENCODING_UTF8_KNOWN && enc == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = enc = ZIP_ENCODING_UTF8_KNOWN; + + if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII) + return ZIP_ENCODING_ERROR; + } + + return enc; +} + + +static zip_uint32_t +_zip_unicode_to_utf8_len(zip_uint32_t codepoint) +{ + if (codepoint < 0x0080) + return 1; + if (codepoint < 0x0800) + return 2; + if (codepoint < 0x10000) + return 3; + return 4; +} + + +static zip_uint32_t +_zip_unicode_to_utf8(zip_uint32_t codepoint, zip_uint8_t *buf) +{ + if (codepoint < 0x0080) { + buf[0] = codepoint & 0xff; + return 1; + } + if (codepoint < 0x0800) { + buf[0] = (zip_uint8_t)(UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f)); + buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); + return 2; + } + if (codepoint < 0x10000) { + buf[0] = (zip_uint8_t)(UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f)); + buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f)); + buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); + return 3; + } + buf[0] = (zip_uint8_t)(UTF_8_LEN_4_MATCH | ((codepoint >> 18) & 0x07)); + buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 12) & 0x3f)); + buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f)); + buf[3] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); + return 4; +} + + +zip_uint8_t * +_zip_cp437_to_utf8(const zip_uint8_t * const _cp437buf, zip_uint32_t len, + zip_uint32_t *utf8_lenp, zip_error_t *error) +{ + zip_uint8_t *cp437buf = (zip_uint8_t *)_cp437buf; + zip_uint8_t *utf8buf; + zip_uint32_t buflen, i, offset; + + if (len == 0) { + if (utf8_lenp) + *utf8_lenp = 0; + return NULL; + } + + buflen = 1; + for (i=0; i +#elif defined(HAVE_INTTYPES_H_LIBZIP) +#include +#elif defined(HAVE_SYS_TYPES_H_LIBZIP) +#include +#endif + +#if defined(HAVE_INT8_T_LIBZIP) +typedef int8_t zip_int8_t; +#elif defined(HAVE___INT8_LIBZIP) +typedef __int8 zip_int8_t; +#else +typedef signed char zip_int8_t; +#endif +#if defined(HAVE_UINT8_T_LIBZIP) +typedef uint8_t zip_uint8_t; +#elif defined(HAVE___INT8_LIBZIP) +typedef unsigned __int8 zip_uint8_t; +#else +typedef unsigned char zip_uint8_t; +#endif +#if defined(HAVE_INT16_T_LIBZIP) +typedef int16_t zip_int16_t; +#elif defined(HAVE___INT16_LIBZIP) +typedef __int16 zip_int16_t; +#elif defined(SHORT_LIBZIP) && SHORT_LIBZIP == 2 +typedef signed short zip_int16_t; +#endif +#if defined(HAVE_UINT16_T_LIBZIP) +typedef uint16_t zip_uint16_t; +#elif defined(HAVE___INT16_LIBZIP) +typedef unsigned __int16 zip_uint16_t; +#elif defined(SHORT_LIBZIP) && SHORT_LIBZIP == 2 +typedef unsigned short zip_uint16_t; +#endif +#if defined(HAVE_INT32_T_LIBZIP) +typedef int32_t zip_int32_t; +#elif defined(HAVE___INT32_LIBZIP) +typedef __int32 zip_int32_t; +#elif defined(INT_LIBZIP) && INT_LIBZIP == 4 +typedef signed int zip_int32_t; +#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 4 +typedef signed long zip_int32_t; +#endif +#if defined(HAVE_UINT32_T_LIBZIP) +typedef uint32_t zip_uint32_t; +#elif defined(HAVE___INT32_LIBZIP) +typedef unsigned __int32 zip_uint32_t; +#elif defined(INT_LIBZIP) && INT_LIBZIP == 4 +typedef unsigned int zip_uint32_t; +#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 4 +typedef unsigned long zip_uint32_t; +#endif +#if defined(HAVE_INT64_T_LIBZIP) +typedef int64_t zip_int64_t; +#elif defined(HAVE___INT64_LIBZIP) +typedef __int64 zip_int64_t; +#elif defined(LONG_LIBZIP) && LONG_LIBZIP == 8 +typedef signed long zip_int64_t; +#elif defined(LONG_LONG_LIBZIP) && LONG_LONG_LIBZIP == 8 +typedef signed long long zip_int64_t; +#endif +#if defined(HAVE_UINT64_T_LIBZIP) +typedef uint64_t zip_uint64_t; +#elif defined(HAVE___INT64_LIBZIP) +typedef unsigned __int64 zip_uint64_t; +#elif defined(LONG_LIBZIP) && LONG_LONG_LIBZIP == 8 +typedef unsigned long zip_uint64_t; +#elif defined(LONG_LONG_LIBZIP) && LONG_LONG_LIBZIP == 8 +typedef unsigned long long zip_uint64_t; +#endif + +#define ZIP_INT8_MIN (-ZIP_INT8_MAX-1) +#define ZIP_INT8_MAX 0x7f +#define ZIP_UINT8_MAX 0xff + +#define ZIP_INT16_MIN (-ZIP_INT16_MAX-1) +#define ZIP_INT16_MAX 0x7fff +#define ZIP_UINT16_MAX 0xffff + +#define ZIP_INT32_MIN (-ZIP_INT32_MAX-1L) +#define ZIP_INT32_MAX 0x7fffffffL +#define ZIP_UINT32_MAX 0xffffffffLU + +#define ZIP_INT64_MIN (-ZIP_INT64_MAX-1LL) +#define ZIP_INT64_MAX 0x7fffffffffffffffLL +#define ZIP_UINT64_MAX 0xffffffffffffffffULL + +#endif /* zipconf.h */ diff --git a/app/jni/zipint.h b/app/jni/zipint.h new file mode 100644 index 0000000..d912b7d --- /dev/null +++ b/app/jni/zipint.h @@ -0,0 +1,547 @@ +#ifndef _HAD_ZIPINT_H +#define _HAD_ZIPINT_H + +/* + zipint.h -- internal declarations. + Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "compat.h" + +#include + +#ifndef _ZIP_COMPILING_DEPRECATED +#define ZIP_DISABLE_DEPRECATED +#endif + +#include "zip.h" + +#define CENTRAL_MAGIC "PK\1\2" +#define LOCAL_MAGIC "PK\3\4" +#define EOCD_MAGIC "PK\5\6" +#define DATADES_MAGIC "PK\7\10" +#define EOCD64LOC_MAGIC "PK\6\7" +#define EOCD64_MAGIC "PK\6\6" +#define CDENTRYSIZE 46u +#define LENTRYSIZE 30 +#define MAXCOMLEN 65536 +#define MAXEXTLEN 65536 +#define EOCDLEN 22 +#define EOCD64LOCLEN 20 +#define EOCD64LEN 56 +#define CDBUFSIZE (MAXCOMLEN+EOCDLEN+EOCD64LOCLEN) +#define BUFSIZE 8192 +#define EFZIP64SIZE 28 +#define EF_WINZIP_AES_SIZE 7 + +#define ZIP_CM_REPLACED_DEFAULT (-2) +#define ZIP_CM_WINZIP_AES 99 /* Winzip AES encrypted */ + +#define ZIP_CM_IS_DEFAULT(x) ((x) == ZIP_CM_DEFAULT || (x) == ZIP_CM_REPLACED_DEFAULT) +#define ZIP_CM_ACTUAL(x) ((zip_uint16_t)(ZIP_CM_IS_DEFAULT(x) ? ZIP_CM_DEFLATE : (x))) + +#define ZIP_EF_UTF_8_COMMENT 0x6375 +#define ZIP_EF_UTF_8_NAME 0x7075 +#define ZIP_EF_WINZIP_AES 0x9901 +#define ZIP_EF_ZIP64 0x0001 + +#define ZIP_EF_IS_INTERNAL(id) ((id) == ZIP_EF_UTF_8_COMMENT || (id) == ZIP_EF_UTF_8_NAME || (id) == ZIP_EF_WINZIP_AES || (id) == ZIP_EF_ZIP64) + +/* according to unzip-6.0's zipinfo.c, this corresponds to a regular file with rw permissions for everyone */ +#define ZIP_EXT_ATTRIB_DEFAULT (0100666u<<16) +/* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */ +#define ZIP_EXT_ATTRIB_DEFAULT_DIR (0040777u<<16) + + +#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b)) + +/* This section contains API that won't materialize like this. It's + placed in the internal section, pending cleanup. */ + +/* flags for compression and encryption sources */ + +#define ZIP_CODEC_DECODE 0 /* decompress/decrypt (encode flag not set) */ +#define ZIP_CODEC_ENCODE 1 /* compress/encrypt */ + +typedef zip_source_t *(*zip_encryption_implementation)(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); + +zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t method, int operation); + +enum zip_compression_status { + ZIP_COMPRESSION_OK, + ZIP_COMPRESSION_END, + ZIP_COMPRESSION_ERROR, + ZIP_COMPRESSION_NEED_DATA +}; +typedef enum zip_compression_status zip_compression_status_t; + +struct zip_compression_algorithm { + /* called once to create new context */ + void *(*allocate)(zip_uint16_t method, int compression_flags, zip_error_t *error); + /* called once to free context */ + void (*deallocate)(void *ctx); + + /* get compression specific general purpose bitflags */ + int (*compression_flags)(void *ctx); + + /* start processing */ + bool (*start)(void *ctx); + /* stop processing */ + bool (*end)(void *ctx); + + /* provide new input data, remains valid until next call to input or end */ + bool (*input)(void *ctx, zip_uint8_t *data, zip_uint64_t length); + + /* all input data has been provided */ + void (*end_of_input)(void *ctx); + + /* process input data, writing to data, which has room for length bytes, update length to number of bytes written */ + zip_compression_status_t (*process)(void *ctx, zip_uint8_t *data, zip_uint64_t *length); +}; +typedef struct zip_compression_algorithm zip_compression_algorithm_t; + +extern zip_compression_algorithm_t zip_algorithm_bzip2_compress; +extern zip_compression_algorithm_t zip_algorithm_bzip2_decompress; +extern zip_compression_algorithm_t zip_algorithm_deflate_compress; +extern zip_compression_algorithm_t zip_algorithm_deflate_decompress; + +bool zip_compression_method_supported(zip_int32_t method, bool compress); + +/* This API is not final yet, but we need it internally, so it's private for now. */ + +const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, int, zip_uint16_t *); + +/* This section contains API that is of limited use until support for + user-supplied compression/encryption implementation is finished. + Thus we will keep it private for now. */ + +typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd); +zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, int compression_flags); +zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int); +zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm); +zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *); +zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error); +zip_source_t *zip_source_pkware(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); +int zip_source_remove(zip_source_t *); +zip_int64_t zip_source_supports(zip_source_t *src); +zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t); +zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); +zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); + + +/* error source for layered sources */ + +enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL }; + +/* directory entry: general purpose bit flags */ + +#define ZIP_GPBF_ENCRYPTED 0x0001u /* is encrypted */ +#define ZIP_GPBF_DATA_DESCRIPTOR 0x0008u /* crc/size after file data */ +#define ZIP_GPBF_STRONG_ENCRYPTION 0x0040u /* uses strong encryption */ +#define ZIP_GPBF_ENCODING_UTF_8 0x0800u /* file name encoding is UTF-8 */ + + +/* extra fields */ +#define ZIP_EF_LOCAL ZIP_FL_LOCAL /* include in local header */ +#define ZIP_EF_CENTRAL ZIP_FL_CENTRAL /* include in central directory */ +#define ZIP_EF_BOTH (ZIP_EF_LOCAL|ZIP_EF_CENTRAL) /* include in both */ + +#define ZIP_FL_FORCE_ZIP64 1024 /* force zip64 extra field (_zip_dirent_write) */ + +#define ZIP_FL_ENCODING_ALL (ZIP_FL_ENC_GUESS|ZIP_FL_ENC_CP437|ZIP_FL_ENC_UTF_8) + + +/* encoding type */ +enum zip_encoding_type { + ZIP_ENCODING_UNKNOWN, /* not yet analyzed */ + ZIP_ENCODING_ASCII, /* plain ASCII */ + ZIP_ENCODING_UTF8_KNOWN, /* is UTF-8 */ + ZIP_ENCODING_UTF8_GUESSED, /* possibly UTF-8 */ + ZIP_ENCODING_CP437, /* Code Page 437 */ + ZIP_ENCODING_ERROR /* should be UTF-8 but isn't */ +}; + +typedef enum zip_encoding_type zip_encoding_type_t; + +struct zip_hash; +struct zip_progress; + +typedef struct zip_cdir zip_cdir_t; +typedef struct zip_dirent zip_dirent_t; +typedef struct zip_entry zip_entry_t; +typedef struct zip_extra_field zip_extra_field_t; +typedef struct zip_string zip_string_t; +typedef struct zip_buffer zip_buffer_t; +typedef struct zip_hash zip_hash_t; +typedef struct zip_progress zip_progress_t; + +/* zip archive, part of API */ + +struct zip { + zip_source_t *src; /* data source for archive */ + unsigned int open_flags; /* flags passed to zip_open */ + zip_error_t error; /* error information */ + + unsigned int flags; /* archive global flags */ + unsigned int ch_flags; /* changed archive global flags */ + + char *default_password; /* password used when no other supplied */ + + zip_string_t *comment_orig; /* archive comment */ + zip_string_t *comment_changes; /* changed archive comment */ + bool comment_changed; /* whether archive comment was changed */ + + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ + zip_entry_t *entry; /* entries */ + + unsigned int nopen_source; /* number of open sources using archive */ + unsigned int nopen_source_alloc; /* number of sources allocated */ + zip_source_t **open_source; /* open sources using archive */ + + zip_hash_t *names; /* hash table for name lookup */ + + zip_progress_t *progress; /* progress callback for zip_close() */ +}; + +/* file in zip archive, part of API */ + +struct zip_file { + zip_t *za; /* zip archive containing this file */ + zip_error_t error; /* error information */ + bool eof; + zip_source_t *src; /* data source */ +}; + +/* zip archive directory entry (central or local) */ + +#define ZIP_DIRENT_COMP_METHOD 0x0001u +#define ZIP_DIRENT_FILENAME 0x0002u +#define ZIP_DIRENT_COMMENT 0x0004u +#define ZIP_DIRENT_EXTRA_FIELD 0x0008u +#define ZIP_DIRENT_ATTRIBUTES 0x0010u +#define ZIP_DIRENT_LAST_MOD 0x0020u +#define ZIP_DIRENT_ENCRYPTION_METHOD 0x0040u +#define ZIP_DIRENT_PASSWORD 0x0080u +#define ZIP_DIRENT_ALL ZIP_UINT32_MAX + +struct zip_dirent { + zip_uint32_t changed; + bool local_extra_fields_read; /* whether we already read in local header extra fields */ + bool cloned; /* whether this instance is cloned, and thus shares non-changed strings */ + + bool crc_valid; /* if CRC is valid (sometimes not for encrypted archives) */ + + zip_uint16_t version_madeby; /* (c) version of creator */ + zip_uint16_t version_needed; /* (cl) version needed to extract */ + zip_uint16_t bitflags; /* (cl) general purpose bit flag */ + zip_int32_t comp_method; /* (cl) compression method used (uint16 and ZIP_CM_DEFAULT (-1)) */ + time_t last_mod; /* (cl) time of last modification */ + zip_uint32_t crc; /* (cl) CRC-32 of uncompressed data */ + zip_uint64_t comp_size; /* (cl) size of compressed data */ + zip_uint64_t uncomp_size; /* (cl) size of uncompressed data */ + zip_string_t *filename; /* (cl) file name (NUL-terminated) */ + zip_extra_field_t *extra_fields; /* (cl) extra fields, parsed */ + zip_string_t *comment; /* (c) file comment */ + zip_uint32_t disk_number; /* (c) disk number start */ + zip_uint16_t int_attrib; /* (c) internal file attributes */ + zip_uint32_t ext_attrib; /* (c) external file attributes */ + zip_uint64_t offset; /* (c) offset of local header */ + + zip_uint16_t compression_level; /* level of compression to use (never valid in orig) */ + zip_uint16_t encryption_method; /* encryption method, computed from other fields */ + char *password; /* file specific encryption password */ +}; + +/* zip archive central directory */ + +struct zip_cdir { + zip_entry_t *entry; /* directory entries */ + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ + + zip_uint64_t size; /* size of central directory */ + zip_uint64_t offset; /* offset of central directory in file */ + zip_string_t *comment; /* zip archive comment */ + bool is_zip64; /* central directory in zip64 format */ +}; + +struct zip_extra_field { + zip_extra_field_t *next; + zip_flags_t flags; /* in local/central header */ + zip_uint16_t id; /* header id */ + zip_uint16_t size; /* data size */ + zip_uint8_t *data; +}; + +enum zip_source_write_state { + ZIP_SOURCE_WRITE_CLOSED, /* write is not in progress */ + ZIP_SOURCE_WRITE_OPEN, /* write is in progress */ + ZIP_SOURCE_WRITE_FAILED, /* commit failed, only rollback allowed */ + ZIP_SOURCE_WRITE_REMOVED /* file was removed */ +}; +typedef enum zip_source_write_state zip_source_write_state_t; + +struct zip_source { + zip_source_t *src; + union { + zip_source_callback f; + zip_source_layered_callback l; + } cb; + void *ud; + zip_error_t error; + zip_int64_t supports; /* supported commands */ + unsigned int open_count; /* number of times source was opened (directly or as lower layer) */ + zip_source_write_state_t write_state; /* whether source is open for writing */ + bool source_closed; /* set if source archive is closed */ + zip_t *source_archive; /* zip archive we're reading from, NULL if not from archive */ + unsigned int refcount; + bool eof; /* EOF reached */ + bool had_read_error; /* a previous ZIP_SOURCE_READ reported an error */ +}; + +#define ZIP_SOURCE_IS_OPEN_READING(src) ((src)->open_count > 0) +#define ZIP_SOURCE_IS_OPEN_WRITING(src) ((src)->write_state == ZIP_SOURCE_WRITE_OPEN) +#define ZIP_SOURCE_IS_LAYERED(src) ((src)->src != NULL) + +/* entry in zip archive directory */ + +struct zip_entry { + zip_dirent_t *orig; + zip_dirent_t *changes; + zip_source_t *source; + bool deleted; +}; + + +/* file or archive comment, or filename */ + +struct zip_string { + zip_uint8_t *raw; /* raw string */ + zip_uint16_t length; /* length of raw string */ + enum zip_encoding_type encoding; /* autorecognized encoding */ + zip_uint8_t *converted; /* autoconverted string */ + zip_uint32_t converted_length; /* length of converted */ +}; + + +/* bounds checked access to memory buffer */ + +struct zip_buffer { + bool ok; + bool free_data; + + zip_uint8_t *data; + zip_uint64_t size; + zip_uint64_t offset; +}; + +/* which files to write in which order */ + +struct zip_filelist { + zip_uint64_t idx; +/* TODO const char *name; */ +}; + +typedef struct zip_filelist zip_filelist_t; + + +extern const char * const _zip_err_str[]; +extern const int _zip_nerr_str; +extern const int _zip_err_type[]; + +#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define ZIP_ENTRY_CHANGED(e, f) ((e)->changes && ((e)->changes->changed & (f))) +#define ZIP_ENTRY_DATA_CHANGED(x) ((x)->source != NULL) +#define ZIP_ENTRY_HAS_CHANGES(e) (ZIP_ENTRY_DATA_CHANGED(e) || (e)->deleted || ZIP_ENTRY_CHANGED((e), ZIP_DIRENT_ALL)) + +#define ZIP_IS_RDONLY(za) ((za)->ch_flags & ZIP_AFL_RDONLY) + + +#ifdef HAVE_EXPLICIT_MEMSET +#define _zip_crypto_clear(b, l) explicit_memset((b), 0, (l)) +#else +#ifdef HAVE_EXPLICIT_BZERO +#define _zip_crypto_clear(b, l) explicit_bzero((b), (l)) +#else +#define _zip_crypto_clear(b, l) memset((b), 0, (l)) +#endif +#endif + + +zip_int64_t _zip_add_entry(zip_t *); + +zip_uint8_t *_zip_buffer_data(zip_buffer_t *buffer); +bool _zip_buffer_eof(zip_buffer_t *buffer); +void _zip_buffer_free(zip_buffer_t *buffer); +zip_uint8_t *_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length); +zip_uint16_t _zip_buffer_get_16(zip_buffer_t *buffer); +zip_uint32_t _zip_buffer_get_32(zip_buffer_t *buffer); +zip_uint64_t _zip_buffer_get_64(zip_buffer_t *buffer); +zip_uint8_t _zip_buffer_get_8(zip_buffer_t *buffer); +zip_uint64_t _zip_buffer_left(zip_buffer_t *buffer); +zip_buffer_t *_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size); +zip_buffer_t *_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error); +zip_uint64_t _zip_buffer_offset(zip_buffer_t *buffer); +bool _zip_buffer_ok(zip_buffer_t *buffer); +zip_uint8_t *_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length); +int _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length); +int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i); +int _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i); +int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i); +int _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i); +zip_uint64_t _zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length); +int _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length); +int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset); +zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer); + +int _zip_cdir_compute_crc(zip_t *, uLong *); +void _zip_cdir_free(zip_cdir_t *); +bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error); +zip_cdir_t *_zip_cdir_new(zip_uint64_t, zip_error_t *); +zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors); +void _zip_deregister_source(zip_t *za, zip_source_t *src); + +zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *); +void _zip_dirent_free(zip_dirent_t *); +void _zip_dirent_finalize(zip_dirent_t *); +void _zip_dirent_init(zip_dirent_t *); +bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t); +zip_dirent_t *_zip_dirent_new(void); +zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error); +void _zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64); +zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t, zip_error_t *); +int _zip_dirent_write(zip_t *za, zip_dirent_t *dirent, zip_flags_t flags); + +zip_extra_field_t *_zip_ef_clone(const zip_extra_field_t *, zip_error_t *); +zip_extra_field_t *_zip_ef_delete_by_id(zip_extra_field_t *, zip_uint16_t, zip_uint16_t, zip_flags_t); +void _zip_ef_free(zip_extra_field_t *); +const zip_uint8_t *_zip_ef_get_by_id(const zip_extra_field_t *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, zip_error_t *); +zip_extra_field_t *_zip_ef_merge(zip_extra_field_t *, zip_extra_field_t *); +zip_extra_field_t *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t); +bool _zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_extra_field_t **, zip_error_t *); +zip_extra_field_t *_zip_ef_remove_internal(zip_extra_field_t *); +zip_uint16_t _zip_ef_size(const zip_extra_field_t *, zip_flags_t); +int _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags); + +void _zip_entry_finalize(zip_entry_t *); +void _zip_entry_init(zip_entry_t *); + +void _zip_error_clear(zip_error_t *); +void _zip_error_get(const zip_error_t *, int *, int *); + +void _zip_error_copy(zip_error_t *dst, const zip_error_t *src); +void _zip_error_set_from_source(zip_error_t *, zip_source_t *); + +const zip_uint8_t *_zip_extract_extra_field_by_id(zip_error_t *, zip_uint16_t, int, const zip_uint8_t *, zip_uint16_t, zip_uint16_t *); + +int _zip_file_extra_field_prepare_for_change(zip_t *, zip_uint64_t); +int _zip_file_fillbuf(void *, size_t, zip_file_t *); +zip_uint64_t _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error); +zip_uint64_t _zip_file_get_offset(const zip_t *, zip_uint64_t, zip_error_t *); + +int _zip_filerange_crc(zip_source_t *src, zip_uint64_t offset, zip_uint64_t length, uLong *crcp, zip_error_t *error); + +zip_dirent_t *_zip_get_dirent(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *); + +enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type); +zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t, zip_uint32_t *, zip_error_t *); + +bool _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error); +bool _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *key, zip_error_t *error); +void _zip_hash_free(zip_hash_t *hash); +zip_int64_t _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error); +zip_hash_t *_zip_hash_new(zip_error_t *error); +bool _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error); +bool _zip_hash_revert(zip_hash_t *hash, zip_error_t *error); + +zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *); + +void _zip_progress_end(zip_progress_t *progress); +void _zip_progress_free(zip_progress_t *progress); +zip_progress_t *_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud); +void _zip_progress_start(zip_progress_t *progress); +void _zip_progress_subrange(zip_progress_t *progress, double start, double end); +void _zip_progress_update(zip_progress_t *progress, double value); + +bool zip_random(zip_uint8_t *buffer, zip_uint16_t length); + +int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error); +int _zip_read_at_offset(zip_source_t *src, zip_uint64_t offset, unsigned char *b, size_t length, zip_error_t *error); +zip_uint8_t *_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error); +int _zip_read_local_ef(zip_t *, zip_uint64_t); +zip_string_t *_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t lenght, bool nulp, zip_error_t *error); +int _zip_register_source(zip_t *za, zip_source_t *src); + +void _zip_set_open_error(int *zep, const zip_error_t *err, int ze); + +zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command); +bool _zip_source_eof(zip_source_t *); +zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error); +zip_int8_t zip_source_get_compression_flags(zip_source_t *); +bool _zip_source_had_error(zip_source_t *); +void _zip_source_invalidate(zip_source_t *src); +zip_source_t *_zip_source_new(zip_error_t *error); +int _zip_source_set_source_archive(zip_source_t *, zip_t *); +zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error); +zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *); + +int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error); +int _zip_string_equal(const zip_string_t *, const zip_string_t *); +void _zip_string_free(zip_string_t *); +zip_uint32_t _zip_string_crc32(const zip_string_t *); +const zip_uint8_t *_zip_string_get(zip_string_t *, zip_uint32_t *, zip_flags_t, zip_error_t *); +zip_uint16_t _zip_string_length(const zip_string_t *); +zip_string_t *_zip_string_new(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_error_t *); +int _zip_string_write(zip_t *za, const zip_string_t *string); + +int _zip_changed(const zip_t *, zip_uint64_t *); +const char *_zip_get_name(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *); +int _zip_local_header_read(zip_t *, int); +void *_zip_memdup(const void *, size_t, zip_error_t *); +zip_int64_t _zip_name_locate(zip_t *, const char *, zip_flags_t, zip_error_t *); +zip_t *_zip_new(zip_error_t *); + +zip_int64_t _zip_file_replace(zip_t *, zip_uint64_t, const char *, zip_source_t *, zip_flags_t); +int _zip_set_name(zip_t *, zip_uint64_t, const char *, zip_flags_t); +void _zip_u2d_time(time_t, zip_uint16_t *, zip_uint16_t *); +int _zip_unchange(zip_t *, zip_uint64_t, int); +void _zip_unchange_data(zip_entry_t *); +int _zip_write(zip_t *za, const void *data, zip_uint64_t length); + +#endif /* zipint.h */ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100755 index 0000000..6e7ffa9 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100755 index 0000000..366e556 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/io/github/xausky/bh3modmanager/FusionZip.java b/app/src/main/java/io/github/xausky/bh3modmanager/FusionZip.java new file mode 100755 index 0000000..bb8bb18 --- /dev/null +++ b/app/src/main/java/io/github/xausky/bh3modmanager/FusionZip.java @@ -0,0 +1,12 @@ +package io.github.xausky.bh3modmanager; + +/** + * Created by xausky on 2018/2/2. + */ + +public class FusionZip { + public static native int patchZip(String backupDir, String fusionDir, String prefix, String target); + static{ + System.loadLibrary("zip"); + } +} diff --git a/app/src/main/java/io/github/xausky/bh3modmanager/MainActivity.java b/app/src/main/java/io/github/xausky/bh3modmanager/MainActivity.java new file mode 100755 index 0000000..33b6476 --- /dev/null +++ b/app/src/main/java/io/github/xausky/bh3modmanager/MainActivity.java @@ -0,0 +1,32 @@ +package io.github.xausky.bh3modmanager; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.Button; +import android.widget.ListView; + +public class MainActivity extends AppCompatActivity { + private MainService service; + private ModsAdapter adapter = null; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + Button launch = findViewById(R.id.launch); + ListView mods = findViewById(R.id.mods); + adapter = new ModsAdapter(this); + mods.setAdapter(adapter); + service = new MainService(this); + service.setAdapter(adapter); + service.setLaunch(launch); + service.start(); + launch.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + service.launch(); + } + }); + } +} diff --git a/app/src/main/java/io/github/xausky/bh3modmanager/MainApplication.java b/app/src/main/java/io/github/xausky/bh3modmanager/MainApplication.java new file mode 100755 index 0000000..add1fad --- /dev/null +++ b/app/src/main/java/io/github/xausky/bh3modmanager/MainApplication.java @@ -0,0 +1,39 @@ +package io.github.xausky.bh3modmanager; + +import android.app.Application; +import android.content.Context; + +import com.lody.virtual.client.core.VirtualCore; + +/** + * Created by xausky on 2018/2/1. + */ + +public class MainApplication extends Application { + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + try { + VirtualCore.get().startup(base); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public void onCreate() { + super.onCreate(); + VirtualCore virtualCore = VirtualCore.get(); + virtualCore.initialize(new VirtualCore.VirtualInitializer() { + @Override + public void onMainProcess() { + } + @Override + public void onVirtualProcess() { + } + @Override + public void onServerProcess() { + } + }); + } +} diff --git a/app/src/main/java/io/github/xausky/bh3modmanager/MainService.java b/app/src/main/java/io/github/xausky/bh3modmanager/MainService.java new file mode 100755 index 0000000..fc3d10c --- /dev/null +++ b/app/src/main/java/io/github/xausky/bh3modmanager/MainService.java @@ -0,0 +1,272 @@ +package io.github.xausky.bh3modmanager; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.os.Environment; +import android.os.RemoteException; +import android.util.Log; +import android.widget.Button; +import android.widget.CompoundButton; +import android.widget.Toast; + +import com.lody.virtual.client.core.VirtualCore; +import com.lody.virtual.client.ipc.VActivityManager; +import com.lody.virtual.remote.InstallResult; +import com.lody.virtual.remote.InstalledAppInfo; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import static android.content.Context.MODE_PRIVATE; + +/** + * Created by xausky on 2018/2/1. + */ + +public class MainService implements CompoundButton.OnCheckedChangeListener { + private static final String BH3_PACKAGE_NAME = "com.miHoYo.enterprise.NGHSoD"; + private static final String RESOURCE_FILE_NAME_REGEX = "([a-z]|[0-9]){32}"; + private MainActivity context = null; + private ModsAdapter adapter = null; + private String appPath = null; + private String virtualAppPath = null; + private Button launch = null; + private boolean isLaunch = true; + private String storagePath = null; + private SharedPreferences preferences; + + public MainService(MainActivity context) { + this.context = context; + preferences = context.getSharedPreferences("mods_install_state", MODE_PRIVATE); + } + + public ModsAdapter getAdapter() { + return adapter; + } + + public void setAdapter(ModsAdapter adapter) { + this.adapter = adapter; + storagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/BH3Mods"; + File storage = new File(storagePath); + if(!storage.exists()){ + if(!storage.mkdir()){ + Toast.makeText(context, "无法创建模组目录,程序退出。", Toast.LENGTH_LONG).show(); + context.finish(); + } + } + File[] mods = storage.listFiles(new FileFilter() { + @Override + public boolean accept(File file) { + return file.getName().endsWith(".zip"); + } + }); + for(File file: mods){ + String name = file.getName().substring(0,file.getName().length() - 4 ); + adapter.getMods().add(new Mod(name, preferences.getBoolean(name, false))); + } + adapter.setListener(this); + } + + public Button getLaunch() { + return launch; + } + + public void setLaunch(Button launch) { + this.launch = launch; + } + + private String getAppPath(){ + List applications = context.getPackageManager().getInstalledApplications(0); + for (ApplicationInfo info : applications) { + if (BH3_PACKAGE_NAME.equals(info.packageName)) { + return info.sourceDir; + } + } + return null; + } + + public void start(){ + appPath = getAppPath(); + if (appPath == null){ + Toast.makeText(context, "未安装崩坏3rd客户端,程序退出。", Toast.LENGTH_LONG).show(); + context.finish(); + } + InstalledAppInfo virtualAppInfo = VirtualCore.get().getInstalledAppInfo(BH3_PACKAGE_NAME, 0); + if(virtualAppInfo != null){ + virtualAppPath = virtualAppInfo.apkPath; + Log.d("BH3ModManager", "V APP Installed: " + virtualAppInfo.apkPath); + }else { + Toast.makeText(context, "未安装底包,正在安装。", Toast.LENGTH_LONG).show(); + final ProgressDialog dialog = ProgressDialog.show(context, "请稍等", "正在安装崩坏3到虚拟环境,该过程大概需要2到3分钟,只需要运行一次。", false, false); + Thread installThread = new Thread(){ + @Override + public void run() { + InstallResult result = VirtualCore.get().installPackage(appPath, 0); + if(result.isSuccess){ + InstalledAppInfo virtualAppInfo = VirtualCore.get().getInstalledAppInfo(BH3_PACKAGE_NAME, 0); + virtualAppPath = virtualAppInfo.apkPath; + } + Log.d("BH3ModManager", "Install APP: " + result.isSuccess + ", Error: " + result.error); + dialog.dismiss(); + } + }; + installThread.start(); + } + } + + public void launch(){ + if(isLaunch){ + final ProgressDialog dialog = ProgressDialog.show(context, "请稍等", "正在启动崩坏3", false, false); + final Intent intent = VirtualCore.get().getLaunchIntent(BH3_PACKAGE_NAME, 0); + VirtualCore.get().setUiCallback(intent, new VirtualCore.UiCallback(){ + @Override + public void onAppOpened(String s, int i) throws RemoteException { + dialog.dismiss(); + } + }); + Thread startThread = new Thread() { + @Override + public void run() { + VActivityManager.get().startActivity(intent, 0); + } + }; + startThread.start(); + }else { + final ProgressDialog dialog = ProgressDialog.show(context, "请稍等", "正在安装模组补丁到崩坏3", false, false); + Thread installThread = new Thread(){ + @Override + public void run() { + String fusionDirPath = context.getCacheDir().getAbsolutePath() + "/ModsFusion"; + String backupDirPath = context.getFilesDir().getAbsolutePath() + "/ModsBackup"; + File fusionDir = new File(fusionDirPath); + deleteFile(fusionDir); + fusionDir.mkdir(); + File backupDir = new File(backupDirPath); + if(!backupDir.exists()){ + backupDir.mkdir(); + } + //开始解压模组文件 + SharedPreferences.Editor editor = preferences.edit(); + for(final Mod mod : adapter.getMods()){ + editor.putBoolean(mod.name, mod.enable); + if(mod.enable){ + try { + final String name = unzipFileByRegex(storagePath + "/" + mod.name + ".zip", fusionDirPath, RESOURCE_FILE_NAME_REGEX); + + if(name != null){ + launch.post(new Runnable() { + @Override + public void run() { + Toast.makeText(context,"安装模组文件冲突:"+ mod.name + "!" + name, Toast.LENGTH_LONG).show(); + } + }); + dialog.dismiss(); + return; + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + editor.commit(); + if(FusionZip.patchZip(backupDirPath, fusionDirPath, "assets/bin/Data", virtualAppPath) != 0){ + launch.post(new Runnable() { + @Override + public void run() { + Toast.makeText(context,"安装模组失败", Toast.LENGTH_LONG).show(); + } + }); + } else { + launch.post(new Runnable() { + @Override + public void run() { + launch.setText(context.getText(R.string.btn_start_content)); + } + }); + isLaunch = true; + } + dialog.dismiss(); + } + }; + installThread.start(); + } + } + + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + launch.setText(context.getText(R.string.btn_apply_content)); + isLaunch = false; + } + private static String unzipFileByRegex(String zipFile, String dir, String regex) throws IOException { + byte[] buffer = new byte[10240]; + ZipFile inputFile = new ZipFile(zipFile); + Enumeration entrys = inputFile.entries(); + while (entrys.hasMoreElements()){ + ZipEntry entry = entrys.nextElement(); + String name = endSubstring(entry.getName(), 32); + if(!entry.isDirectory() && name.matches(regex)){ + File outputFile = new File(dir + "/" + name); + if(outputFile.exists()){ + inputFile.close(); + return entry.getName(); + } + FileOutputStream outputFileStream = new FileOutputStream(outputFile); + InputStream inputStream = inputFile.getInputStream(entry); + int len = 0; + while((len = inputStream.read(buffer)) != -1){ + outputFileStream.write(buffer, 0, len); + } + outputFileStream.close(); + inputStream.close(); + } + } + inputFile.close(); + return null; + } + + private static String endSubstring(String str, int len){ + if(str.length() < len){ + return ""; + } + return str.substring(str.length() - 32, str.length()); + } + + /** + * 通过递归调用删除一个文件夹及下面的所有文件 + * @param file + */ + private static void deleteFile(File file){ + if(!file.exists()){ + return; + } + if(file.isFile()){//表示该文件不是文件夹 + if(!file.delete()){ + Log.d("BH3ModManager", "delete failed: " + file.getAbsolutePath()); + } + }else{ + //首先得到当前的路径 + File[] childFiles = file.listFiles(); + for(File childFile : childFiles){ + deleteFile(childFile); + } + if(!file.delete()){ + Log.d("BH3ModManager", "delete failed: " + file.getAbsolutePath()); + } + } + } +} diff --git a/app/src/main/java/io/github/xausky/bh3modmanager/Mod.java b/app/src/main/java/io/github/xausky/bh3modmanager/Mod.java new file mode 100755 index 0000000..7aa2864 --- /dev/null +++ b/app/src/main/java/io/github/xausky/bh3modmanager/Mod.java @@ -0,0 +1,15 @@ +package io.github.xausky.bh3modmanager; + +/** + * Created by xausky on 2018/2/1. + */ + +public class Mod { + public String name; + public boolean enable; + + public Mod(String name, boolean enable) { + this.name = name; + this.enable = enable; + } +} diff --git a/app/src/main/java/io/github/xausky/bh3modmanager/ModsAdapter.java b/app/src/main/java/io/github/xausky/bh3modmanager/ModsAdapter.java new file mode 100755 index 0000000..0a0db83 --- /dev/null +++ b/app/src/main/java/io/github/xausky/bh3modmanager/ModsAdapter.java @@ -0,0 +1,75 @@ +package io.github.xausky.bh3modmanager; + +import android.content.Context; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.CompoundButton; +import android.widget.Switch; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by xausky on 2018/2/1. + */ + +public class ModsAdapter extends BaseAdapter { + private Context context = null; + private List mods = new ArrayList<>(); + private CompoundButton.OnCheckedChangeListener listener = null; + + public ModsAdapter(Context context) { + this.context = context; + } + + public List getMods() { + return mods; + } + + public void setMods(List mods) { + this.mods = mods; + } + + public void setListener(CompoundButton.OnCheckedChangeListener listener) { + this.listener = listener; + } + + @Override + public int getCount() { + return mods.size(); + } + + @Override + public Object getItem(int i) { + return mods.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + Switch new_view = new Switch(context); + final Mod mod = (Mod) getItem(i); + new_view.setChecked(mod.enable); + new_view.setText(mod.name); + new_view.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24); + new_view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + new_view.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + Log.d("BH3ModManager", compoundButton.getText() + ":" + b); + mod.enable = b; + if(listener != null){ + listener.onCheckedChanged(compoundButton, b); + } + } + }); + return new_view; + } +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100755 index 0000000..ddb26ad --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/flatbutton.xml b/app/src/main/res/drawable/flatbutton.xml new file mode 100644 index 0000000..0ec7e2d --- /dev/null +++ b/app/src/main/res/drawable/flatbutton.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100755 index 0000000..3a37cf6 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100755 index 0000000..cca731a --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,18 @@ + + + +