Browse code

merge master

aCaB authored on 2012/01/05 06:55:07
Showing 114 changed files
... ...
@@ -1,3 +1,25 @@
1
+Thu Nov  3 22:42:28 CET 2011 (acab)
2
+-----------------------------------
3
+ * libclamav/lzma_iface.c: stfu on (but still refuse) big lzma allocs
4
+
5
+Tue Nov  1 12:26:46 CET 2011 (acab)
6
+-----------------------------------
7
+ * libclamav: Add 7z SFX support (b#3063)
8
+
9
+Thu Dec 15 21:40:57 CET 2011 (tk)
10
+---------------------------------
11
+ * libclamav/matcher-ac.c: improve negation of single elements - handle
12
+			   !(xx) (bb#4052)
13
+
14
+Thu Dec 15 18:34:03 EET 2011 (edwin)
15
+------------------------------------
16
+ * libclamav/pdf.c: scan inside encrypted PDF streams and strings when user
17
+		    password is empty (bb #2794).
18
+
19
+Fri Dec  9 16:41:05 CET 2011 (tk)
20
+---------------------------------
21
+ * libclamav/matcher.c: add new offset modifier SEx (bb#4008)
22
+
1 23
 Thu Dec  1 15:07:49 CET 2011 (tk)
2 24
 ---------------------------------
3 25
  * libclamav/readdb.c: allow comments in all db files (bb#3930)
... ...
@@ -46,6 +46,7 @@ clamd_SOURCES = \
46 46
     others.h \
47 47
     shared.h \
48 48
     fan.c \
49
+    fan.h \
49 50
     fan-syscalllib.h
50 51
 
51 52
 AM_CFLAGS=@WERR_CFLAGS@
... ...
@@ -83,7 +83,7 @@ am__clamd_SOURCES_DIST = $(top_srcdir)/shared/output.c \
83 83
 	$(top_srcdir)/shared/misc.h clamd.c tcpserver.c tcpserver.h \
84 84
 	localserver.c localserver.h session.c session.h thrmgr.c \
85 85
 	thrmgr.h server-th.c server.h scanner.c scanner.h others.c \
86
-	others.h shared.h fan.c fan-syscalllib.h
86
+	others.h shared.h fan.c fan.h fan-syscalllib.h
87 87
 @BUILD_CLAMD_TRUE@am_clamd_OBJECTS = output.$(OBJEXT) \
88 88
 @BUILD_CLAMD_TRUE@	optparser.$(OBJEXT) getopt.$(OBJEXT) \
89 89
 @BUILD_CLAMD_TRUE@	misc.$(OBJEXT) clamd.$(OBJEXT) \
... ...
@@ -318,6 +318,7 @@ top_srcdir = @top_srcdir@
318 318
 @BUILD_CLAMD_TRUE@    others.h \
319 319
 @BUILD_CLAMD_TRUE@    shared.h \
320 320
 @BUILD_CLAMD_TRUE@    fan.c \
321
+@BUILD_CLAMD_TRUE@    fan.h \
321 322
 @BUILD_CLAMD_TRUE@    fan-syscalllib.h
322 323
 
323 324
 @BUILD_CLAMD_TRUE@AM_CFLAGS = @WERR_CFLAGS@
... ...
@@ -16546,9 +16546,9 @@ $as_echo "$ac_cv_libbz2_libs" >&6; }
16546 16546
     test -z "$LIBBZ2_PREFIX" || LDFLAGS="$LDFLAGS -L$LIBBZ2_PREFIX/$acl_libdirstem";
16547 16547
 
16548 16548
     have_bzprefix="no"
16549
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzReadOpen in -lbz2" >&5
16550
-$as_echo_n "checking for BZ2_bzReadOpen in -lbz2... " >&6; }
16551
-if ${ac_cv_lib_bz2_BZ2_bzReadOpen+:} false; then :
16549
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzDecompressInit in -lbz2" >&5
16550
+$as_echo_n "checking for BZ2_bzDecompressInit in -lbz2... " >&6; }
16551
+if ${ac_cv_lib_bz2_BZ2_bzDecompressInit+:} false; then :
16552 16552
   $as_echo_n "(cached) " >&6
16553 16553
 else
16554 16554
   ac_check_lib_save_LIBS=$LIBS
... ...
@@ -16562,27 +16562,27 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
16562 16562
 #ifdef __cplusplus
16563 16563
 extern "C"
16564 16564
 #endif
16565
-char BZ2_bzReadOpen ();
16565
+char BZ2_bzDecompressInit ();
16566 16566
 int
16567 16567
 main ()
16568 16568
 {
16569
-return BZ2_bzReadOpen ();
16569
+return BZ2_bzDecompressInit ();
16570 16570
   ;
16571 16571
   return 0;
16572 16572
 }
16573 16573
 _ACEOF
16574 16574
 if ac_fn_c_try_link "$LINENO"; then :
16575
-  ac_cv_lib_bz2_BZ2_bzReadOpen=yes
16575
+  ac_cv_lib_bz2_BZ2_bzDecompressInit=yes
16576 16576
 else
16577
-  ac_cv_lib_bz2_BZ2_bzReadOpen=no
16577
+  ac_cv_lib_bz2_BZ2_bzDecompressInit=no
16578 16578
 fi
16579 16579
 rm -f core conftest.err conftest.$ac_objext \
16580 16580
     conftest$ac_exeext conftest.$ac_ext
16581 16581
 LIBS=$ac_check_lib_save_LIBS
16582 16582
 fi
16583
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzReadOpen" >&5
16584
-$as_echo "$ac_cv_lib_bz2_BZ2_bzReadOpen" >&6; }
16585
-if test "x$ac_cv_lib_bz2_BZ2_bzReadOpen" = xyes; then :
16583
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzDecompressInit" >&5
16584
+$as_echo "$ac_cv_lib_bz2_BZ2_bzDecompressInit" >&6; }
16585
+if test "x$ac_cv_lib_bz2_BZ2_bzDecompressInit" = xyes; then :
16586 16586
   have_bzprefix="yes"
16587 16587
 fi
16588 16588
 
... ...
@@ -581,7 +581,7 @@ then
581 581
     test -z "$LIBBZ2_PREFIX" || LDFLAGS="$LDFLAGS -L$LIBBZ2_PREFIX/$acl_libdirstem";
582 582
 
583 583
     have_bzprefix="no"
584
-    AC_CHECK_LIB([bz2], [BZ2_bzReadOpen], [have_bzprefix="yes"])
584
+    AC_CHECK_LIB([bz2], [BZ2_bzDecompressInit], [have_bzprefix="yes"])
585 585
     if test "x$have_bzprefix" = "xno"; then
586 586
         AC_DEFINE([NOBZ2PREFIX],1,[bzip funtions do not have bz2 prefix])
587 587
     fi
... ...
@@ -9,8 +9,12 @@
9 9
 #include <libkern/OSAtomic.h>
10 10
 #include <libkern/OSMalloc.h>
11 11
 #include <sys/sysctl.h>
12
+#include <sys/systm.h>
12 13
 #include <sys/kauth.h>
13 14
 #include <sys/vnode.h>
15
+#include <sys/uio.h>
16
+#include <sys/conf.h>
17
+#include <miscfs/devfs/devfs.h>
14 18
 
15 19
 #pragma mark ***** Global Resources
16 20
 /* These declarations are required to allocate memory and create locks.
... ...
@@ -776,6 +780,74 @@ SYSCTL_OID(
776 776
 
777 777
 static boolean_t gRegisteredOID = FALSE;
778 778
 
779
+
780
+/* /dev/clamauth handling */
781
+
782
+static int ca_devidx = -1;
783
+static void *ca_devnode = NULL;
784
+
785
+static int ca_open(dev_t dev, int flag, int devtype, proc_t p)
786
+{
787
+    return ENOENT;
788
+}
789
+
790
+static int ca_close(dev_t dev, int flag, int devtype, proc_t p)
791
+{
792
+    return ENOENT;
793
+}
794
+
795
+static int ca_read(dev_t dev, uio_t uio, int ioflag)
796
+{
797
+    return EBADF;
798
+}
799
+
800
+static int ca_write(dev_t dev, uio_t uio, int ioflag)
801
+{
802
+    return EBADF;
803
+}
804
+
805
+static int ca_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, proc_t p)
806
+{
807
+    return EBADF;
808
+}
809
+
810
+static int ca_select(dev_t dev, int flag, void * wql, proc_t p)
811
+{
812
+    return EBADF;
813
+}
814
+
815
+static struct cdevsw clamauth_cdevsw = {
816
+    ca_open,
817
+    ca_close,
818
+    ca_read,
819
+    ca_write,
820
+    ca_ioctl,
821
+    eno_stop,
822
+    eno_reset,
823
+    NULL,
824
+    ca_select,
825
+    eno_mmap,
826
+    eno_strat,
827
+    eno_getc,
828
+    eno_putc,
829
+    0
830
+};
831
+
832
+static int ca_remove(void)
833
+{
834
+    if(ca_devnode)
835
+        devfs_remove(ca_devnode);
836
+
837
+    if(ca_devidx != -1) {
838
+        if(cdevsw_remove(ca_devidx, &clamauth_cdevsw) != ca_devidx) {
839
+            printf("ClamAuth: cdevsw_remove() failed\n");
840
+            return KERN_FAILURE;
841
+        }
842
+    }
843
+
844
+    return KERN_SUCCESS;
845
+}
846
+
779 847
 #pragma mark ***** Start/Stop
780 848
 
781 849
 /* Prototypes for our entry points */
... ...
@@ -789,7 +861,18 @@ extern kern_return_t com_apple_dts_kext_ClamAuth_start(kmod_info_t * ki, void *
789 789
     #pragma unused(d)
790 790
     kern_return_t   err;
791 791
 
792
+    ca_devidx = cdevsw_add(-1, &clamauth_cdevsw);
793
+    if(ca_devidx == -1) {
794
+        printf("ClamAuth: cdevsw_add() failed\n");
795
+        return KERN_FAILURE;
796
+    }
792 797
 
798
+    ca_devnode = devfs_make_node(makedev(ca_devidx, 0), DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0660, "clamauth");
799
+    if(!ca_devnode) {
800
+        printf("ClamAuth: Can't create /dev/clamauth\n");
801
+        return ca_remove();
802
+    }    
803
+    
793 804
     /* Allocate our global resources, needed in order to allocate memory 
794 805
      * and locks throughout the rest of the program.
795 806
      */
... ...
@@ -834,6 +917,7 @@ extern kern_return_t com_apple_dts_kext_ClamAuth_stop(kmod_info_t * ki, void * d
834 834
 {
835 835
     #pragma unused(ki)
836 836
     #pragma unused(d)
837
+    int ret;
837 838
 
838 839
     /* Remove our sysctl handler.  This prevents more threads entering the 
839 840
      * handler and trying to change the configuration.  There is still a 
... ...
@@ -850,6 +934,9 @@ extern kern_return_t com_apple_dts_kext_ClamAuth_stop(kmod_info_t * ki, void * d
850 850
         gRegisteredOID = FALSE;
851 851
     }
852 852
 
853
+    /* remove the character device */
854
+    ret = ca_remove();
855
+
853 856
     /* Shut down the scope listen, if any.  Not that we lock gConfigurationLock 
854 857
      * because RemoveListener requires it to be locked.  Further note that 
855 858
      * we only do this if the lock has actually been allocated.  If the startup 
... ...
@@ -880,5 +967,5 @@ extern kern_return_t com_apple_dts_kext_ClamAuth_stop(kmod_info_t * ki, void * d
880 880
     }
881 881
     
882 882
     printf("ClamAuth_stop: ClamAV kernel driver removed\n");
883
-    return KERN_SUCCESS;
883
+    return ret;
884 884
 }
... ...
@@ -78,6 +78,9 @@ Unpack a local CVD file (main or daily) to current directory.
78 78
 \fB\-\-diff=OLD NEW, \-d OLD NEW\fR
79 79
 Create a diff file for OLD and NEW CVDs/INCDIRs.
80 80
 .TP 
81
+\fB\-\-compare=OLD NEW, \-c OLD NEW\fR
82
+This command will compare two text files and print differences in a cdiff format.
83
+.TP 
81 84
 \fB\-\-run\-cdiff=FILE, \-r FILE\fR
82 85
 Execute update script FILE in current directory.
83 86
 .TP 
... ...
@@ -356,6 +356,8 @@ MalwareName:TargetType:Offset:HexSignature[:MinFL:[MaxFL]]
356 356
 	\item \verb#Sx+n# = start of section \verb+x+'s (counted from 0)
357 357
 	data plus \verb+n+ bytes
358 358
 	\item \verb#Sx-n# = start of section \verb+x+'s data minus \verb+n+ bytes
359
+	\item \verb#SEx# = entire section \verb+x+ (offset must lie within section
360
+	boundaries)
359 361
 	\item \verb#SL+n# = start of last section plus \verb+n+ bytes
360 362
 	\item \verb#SL-n# = start of last section minus \verb+n+ bytes
361 363
     \end{itemize}
362 364
deleted file mode 100644
... ...
@@ -1,138 +0,0 @@
1
-/*
2
- *  Copyright (C) 2009 Sourcefire, Inc.
3
- *
4
- *  Authors: aCaB
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-/* 7zip scanner */
22
-
23
-#if HAVE_CONFIG_H
24
-#include "clamav-config.h"
25
-#endif
26
-
27
-#include <stdio.h>
28
-#include <sys/types.h>
29
-#include <sys/stat.h>
30
-#include <fcntl.h>
31
-
32
-#include "others.h"
33
-#include "lzma_iface.h"
34
-#include "scanners.h"
35
-#include "matcher.h"
36
-#include "7z/7zFile.h"
37
-#include "7z/7zCrc.h"
38
-#include "7z/Archive/7z/7zIn.h"
39
-#include "7z/Archive/7z/7zExtract.h"
40
-
41
-static ISzAlloc allocImp = { __lzma_wrap_alloc, __lzma_wrap_free}, allocTempImp = { __lzma_wrap_alloc, __lzma_wrap_free};
42
-
43
-int cli_7unz (int fd, cli_ctx *ctx) {
44
-    CFileInStream archiveStream;
45
-    CLookToRead lookStream;
46
-    CSzArEx db;
47
-    UInt32 blockIndex = 0xFFFFFFFF;
48
-    unsigned char *buf = NULL;
49
-    size_t bufsz = 0;
50
-    UInt32 i;
51
-    int dupfd, ret = CL_CLEAN;
52
-    unsigned int fu=0;
53
-
54
-    if((dupfd = dup(fd)) == -1) {
55
-	cli_errmsg("cli_7unz: dup() failed\n");
56
-	return CL_EDUP;
57
-    }
58
-    FileInStream_CreateVTable(&archiveStream);
59
-    archiveStream.file.file = fdopen(dupfd, "rb");
60
-    if(!archiveStream.file.file) {
61
-	cli_errmsg("cli_7unz: fdopen() failed\n");
62
-	return CL_EOPEN;
63
-    }
64
-    LookToRead_CreateVTable(&lookStream, False);
65
-    lookStream.realStream = &archiveStream.s;
66
-    LookToRead_Init(&lookStream);
67
-
68
-    SzArEx_Init(&db);
69
-    if(SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) != SZ_OK) {
70
-	SzArEx_Free(&db, &allocImp);
71
-	cli_dbgmsg("cli_7unz: possibly damaged archive\n");
72
-	fclose(archiveStream.file.file);
73
-	return CL_CLEAN;
74
-    }
75
-    for (i = 0; i < db.db.NumFiles; i++) {
76
-	CSzFileItem *f = db.db.Files + i;
77
-        size_t offset;
78
-        size_t usize;
79
-
80
-	if(f->IsDir || !f->Size) continue;
81
-	if(ctx->engine->maxfilesize && f->Size > ctx->engine->maxfilesize) {
82
-	    cli_dbgmsg("cli_7unz: skipping stream due to size limits (%llu vs %llu)\n", (long long)f->Size, (long long)ctx->engine->maxfilesize);
83
-	    continue;
84
-	}
85
-	if(cli_matchmeta(ctx, f->Name, 0, f->Size, 0, i + 1, 0, NULL) == CL_VIRUS) {
86
-	    ret = CL_VIRUS;
87
-	    break;
88
-	}
89
-	if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
90
-	    cli_dbgmsg("cli_7unz: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
91
-	    ret=CL_EMAXFILES;
92
-	    break;
93
-	}
94
-	cli_dbgmsg("cli_7unz: Extracting file %s\n", f->Name);
95
-	if(SzAr_Extract(&db, &lookStream.s, i, &blockIndex, &buf, &bufsz, &offset, &usize, &allocImp, &allocTempImp) == SZ_OK) {
96
-	    char *fname;
97
-	    int ofd;
98
-
99
-	    if(!usize) {
100
-		cli_dbgmsg("cli_7unz: stream uncompressed to an empty file\n");
101
-		continue;
102
-	    }
103
-	    fu++;
104
-	    if(!(fname = cli_gentemp(ctx->engine->tmpdir))) {
105
-		ret = CL_EMEM;
106
-		break;
107
-	    }
108
-	    if((ofd = open(fname, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
109
-		cli_errmsg("cli_7unz: failed to create file %s\n", fname);
110
-		free(fname);
111
-		ret = CL_ECREAT;
112
-		break;
113
-	    }
114
-	    if(cli_writen(ofd, buf, usize) <= 0) {
115
-		close(ofd);
116
-		if(cli_unlink(fname)) ret = CL_EUNLINK;
117
-		else ret = CL_EWRITE;
118
-		free(fname);
119
-		break;
120
-	    }
121
-	    cli_dbgmsg("cli_7unz: extracted to %s\n", fname);
122
-	    lseek(ofd, 0, SEEK_SET);
123
-	    ret = cli_magic_scandesc(ofd, ctx);
124
-	    close(ofd);
125
-	    if(!ctx->engine->keeptmp)
126
-		if(cli_unlink(fname)) ret = CL_EUNLINK;
127
-	    free(fname);
128
-	    if(ret == CL_EUNLINK || ret == CL_VIRUS)
129
-		break;
130
-	} else {
131
-	    cli_dbgmsg("cli_7unz: decompression failed\n");
132
-	}
133
-    }
134
-    if(buf) free(buf);
135
-    SzArEx_Free(&db, &allocImp);
136
-    fclose(archiveStream.file.file);
137
-    return ret;
138
-}
139 1
deleted file mode 100644
... ...
@@ -1,32 +0,0 @@
1
-/*
2
- *  Copyright (C) 2009 Sourcefire, Inc.
3
- *
4
- *  Authors: aCaB
5
- *
6
- *  This program is free software; you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License version 2 as
8
- *  published by the Free Software Foundation.
9
- *
10
- *  This program is distributed in the hope that it will be useful,
11
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
- *  GNU General Public License for more details.
14
- *
15
- *  You should have received a copy of the GNU General Public License
16
- *  along with this program; if not, write to the Free Software
17
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
- *  MA 02110-1301, USA.
19
- */
20
-
21
-#ifndef __7Z_H
22
-#define __7Z_H
23
-
24
-#if HAVE_CONFIG_H
25
-#include "clamav-config.h"
26
-#endif
27
-
28
-#include "others.h"
29
-
30
-int cli_7unz (int, cli_ctx *);
31
-
32
-#endif
33 1
new file mode 100644
... ...
@@ -0,0 +1,203 @@
0
+/* 7z.h -- 7z interface
1
+2010-03-11 : Igor Pavlov : Public domain */
2
+
3
+#ifndef __7Z_H
4
+#define __7Z_H
5
+
6
+#include "7zBuf.h"
7
+
8
+EXTERN_C_BEGIN
9
+
10
+#define k7zStartHeaderSize 0x20
11
+#define k7zSignatureSize 6
12
+extern Byte k7zSignature[k7zSignatureSize];
13
+#define k7zMajorVersion 0
14
+
15
+enum EIdEnum
16
+{
17
+  k7zIdEnd,
18
+  k7zIdHeader,
19
+  k7zIdArchiveProperties,
20
+  k7zIdAdditionalStreamsInfo,
21
+  k7zIdMainStreamsInfo,
22
+  k7zIdFilesInfo,
23
+  k7zIdPackInfo,
24
+  k7zIdUnpackInfo,
25
+  k7zIdSubStreamsInfo,
26
+  k7zIdSize,
27
+  k7zIdCRC,
28
+  k7zIdFolder,
29
+  k7zIdCodersUnpackSize,
30
+  k7zIdNumUnpackStream,
31
+  k7zIdEmptyStream,
32
+  k7zIdEmptyFile,
33
+  k7zIdAnti,
34
+  k7zIdName,
35
+  k7zIdCTime,
36
+  k7zIdATime,
37
+  k7zIdMTime,
38
+  k7zIdWinAttributes,
39
+  k7zIdComment,
40
+  k7zIdEncodedHeader,
41
+  k7zIdStartPos,
42
+  k7zIdDummy
43
+};
44
+
45
+typedef struct
46
+{
47
+  UInt32 NumInStreams;
48
+  UInt32 NumOutStreams;
49
+  UInt64 MethodID;
50
+  CBuf Props;
51
+} CSzCoderInfo;
52
+
53
+void SzCoderInfo_Init(CSzCoderInfo *p);
54
+void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
55
+
56
+typedef struct
57
+{
58
+  UInt32 InIndex;
59
+  UInt32 OutIndex;
60
+} CSzBindPair;
61
+
62
+typedef struct
63
+{
64
+  CSzCoderInfo *Coders;
65
+  CSzBindPair *BindPairs;
66
+  UInt32 *PackStreams;
67
+  UInt64 *UnpackSizes;
68
+  UInt32 NumCoders;
69
+  UInt32 NumBindPairs;
70
+  UInt32 NumPackStreams;
71
+  int UnpackCRCDefined;
72
+  UInt32 UnpackCRC;
73
+
74
+  UInt32 NumUnpackStreams;
75
+} CSzFolder;
76
+
77
+void SzFolder_Init(CSzFolder *p);
78
+UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
79
+int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
80
+UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
81
+UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
82
+
83
+SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
84
+    ILookInStream *stream, UInt64 startPos,
85
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
86
+
87
+typedef struct
88
+{
89
+  UInt32 Low;
90
+  UInt32 High;
91
+} CNtfsFileTime;
92
+
93
+typedef struct
94
+{
95
+  CNtfsFileTime MTime;
96
+  UInt64 Size;
97
+  UInt32 Crc;
98
+  UInt32 Attrib;
99
+  Byte HasStream;
100
+  Byte IsDir;
101
+  Byte IsAnti;
102
+  Byte CrcDefined;
103
+  Byte MTimeDefined;
104
+  Byte AttribDefined;
105
+} CSzFileItem;
106
+
107
+void SzFile_Init(CSzFileItem *p);
108
+
109
+typedef struct
110
+{
111
+  UInt64 *PackSizes;
112
+  Byte *PackCRCsDefined;
113
+  UInt32 *PackCRCs;
114
+  CSzFolder *Folders;
115
+  CSzFileItem *Files;
116
+  UInt32 NumPackStreams;
117
+  UInt32 NumFolders;
118
+  UInt32 NumFiles;
119
+} CSzAr;
120
+
121
+void SzAr_Init(CSzAr *p);
122
+void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
123
+
124
+
125
+/*
126
+  SzExtract extracts file from archive
127
+
128
+  *outBuffer must be 0 before first call for each new archive.
129
+
130
+  Extracting cache:
131
+    If you need to decompress more than one file, you can send
132
+    these values from previous call:
133
+      *blockIndex,
134
+      *outBuffer,
135
+      *outBufferSize
136
+    You can consider "*outBuffer" as cache of solid block. If your archive is solid,
137
+    it will increase decompression speed.
138
+  
139
+    If you use external function, you can declare these 3 cache variables
140
+    (blockIndex, outBuffer, outBufferSize) as static in that external function.
141
+    
142
+    Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
143
+*/
144
+
145
+typedef struct
146
+{
147
+  CSzAr db;
148
+  
149
+  UInt64 startPosAfterHeader;
150
+  UInt64 dataPos;
151
+
152
+  UInt32 *FolderStartPackStreamIndex;
153
+  UInt64 *PackStreamStartPositions;
154
+  UInt32 *FolderStartFileIndex;
155
+  UInt32 *FileIndexToFolderIndexMap;
156
+
157
+  size_t *FileNameOffsets; /* in 2-byte steps */
158
+  CBuf FileNames;  /* UTF-16-LE */
159
+} CSzArEx;
160
+
161
+void SzArEx_Init(CSzArEx *p);
162
+void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
163
+UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
164
+int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
165
+
166
+/*
167
+if dest == NULL, the return value specifies the required size of the buffer,
168
+  in 16-bit characters, including the null-terminating character.
169
+if dest != NULL, the return value specifies the number of 16-bit characters that
170
+  are written to the dest, including the null-terminating character. */
171
+
172
+size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
173
+
174
+SRes SzArEx_Extract(
175
+    const CSzArEx *db,
176
+    ILookInStream *inStream,
177
+    UInt32 fileIndex,         /* index of file */
178
+    UInt32 *blockIndex,       /* index of solid block */
179
+    Byte **outBuffer,         /* pointer to pointer to output buffer (allocated with allocMain) */
180
+    size_t *outBufferSize,    /* buffer size for output buffer */
181
+    size_t *offset,           /* offset of stream for required file in *outBuffer */
182
+    size_t *outSizeProcessed, /* size of file in *outBuffer */
183
+    ISzAlloc *allocMain,
184
+    ISzAlloc *allocTemp);
185
+
186
+
187
+/*
188
+SzArEx_Open Errors:
189
+SZ_ERROR_NO_ARCHIVE
190
+SZ_ERROR_ARCHIVE
191
+SZ_ERROR_UNSUPPORTED
192
+SZ_ERROR_MEM
193
+SZ_ERROR_CRC
194
+SZ_ERROR_INPUT_EOF
195
+SZ_ERROR_FAIL
196
+*/
197
+
198
+SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
199
+
200
+EXTERN_C_END
201
+
202
+#endif
0 203
new file mode 100644
... ...
@@ -0,0 +1,76 @@
0
+/* 7zAlloc.c -- Allocation functions
1
+2010-10-29 : Igor Pavlov : Public domain */
2
+
3
+#include "7zAlloc.h"
4
+
5
+/* #define _SZ_ALLOC_DEBUG */
6
+/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
7
+
8
+#ifdef _SZ_ALLOC_DEBUG
9
+
10
+#ifdef _WIN32
11
+#include <windows.h>
12
+#endif
13
+
14
+#include <stdio.h>
15
+int g_allocCount = 0;
16
+int g_allocCountTemp = 0;
17
+
18
+#endif
19
+
20
+void *SzAlloc(void *p, size_t size)
21
+{
22
+  p = p;
23
+  if (size == 0)
24
+    return 0;
25
+  #ifdef _SZ_ALLOC_DEBUG
26
+  fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
27
+  g_allocCount++;
28
+  #endif
29
+  return malloc(size);
30
+}
31
+
32
+void SzFree(void *p, void *address)
33
+{
34
+  p = p;
35
+  #ifdef _SZ_ALLOC_DEBUG
36
+  if (address != 0)
37
+  {
38
+    g_allocCount--;
39
+    fprintf(stderr, "\nFree; count = %10d", g_allocCount);
40
+  }
41
+  #endif
42
+  free(address);
43
+}
44
+
45
+void *SzAllocTemp(void *p, size_t size)
46
+{
47
+  p = p;
48
+  if (size == 0)
49
+    return 0;
50
+  #ifdef _SZ_ALLOC_DEBUG
51
+  fprintf(stderr, "\nAlloc_temp %10d bytes;  count = %10d", size, g_allocCountTemp);
52
+  g_allocCountTemp++;
53
+  #ifdef _WIN32
54
+  return HeapAlloc(GetProcessHeap(), 0, size);
55
+  #endif
56
+  #endif
57
+  return malloc(size);
58
+}
59
+
60
+void SzFreeTemp(void *p, void *address)
61
+{
62
+  p = p;
63
+  #ifdef _SZ_ALLOC_DEBUG
64
+  if (address != 0)
65
+  {
66
+    g_allocCountTemp--;
67
+    fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
68
+  }
69
+  #ifdef _WIN32
70
+  HeapFree(GetProcessHeap(), 0, address);
71
+  return;
72
+  #endif
73
+  #endif
74
+  free(address);
75
+}
0 76
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+/* 7zAlloc.h -- Allocation functions
1
+2010-10-29 : Igor Pavlov : Public domain */
2
+
3
+#ifndef __7Z_ALLOC_H
4
+#define __7Z_ALLOC_H
5
+
6
+#include <stdlib.h>
7
+
8
+void *SzAlloc(void *p, size_t size);
9
+void SzFree(void *p, void *address);
10
+
11
+void *SzAllocTemp(void *p, size_t size);
12
+void SzFreeTemp(void *p, void *address);
13
+
14
+#endif
... ...
@@ -1,11 +1,15 @@
1 1
 /* 7zBuf.h -- Byte Buffer
2
-2008-10-04 : Igor Pavlov : Public domain */
2
+2009-02-07 : Igor Pavlov : Public domain */
3 3
 
4 4
 #ifndef __7Z_BUF_H
5 5
 #define __7Z_BUF_H
6 6
 
7 7
 #include "Types.h"
8 8
 
9
+#ifdef __cplusplus
10
+extern "C" {
11
+#endif
12
+
9 13
 typedef struct
10 14
 {
11 15
   Byte *data;
... ...
@@ -28,4 +32,8 @@ void DynBuf_SeekToBeg(CDynBuf *p);
28 28
 int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
29 29
 void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
30 30
 
31
+#ifdef __cplusplus
32
+}
33
+#endif
34
+
31 35
 #endif
32 36
new file mode 100644
... ...
@@ -0,0 +1,45 @@
0
+/* 7zBuf2.c -- Byte Buffer
1
+2008-10-04 : Igor Pavlov : Public domain */
2
+
3
+#include <string.h>
4
+#include "7zBuf.h"
5
+
6
+void DynBuf_Construct(CDynBuf *p)
7
+{
8
+  p->data = 0;
9
+  p->size = 0;
10
+  p->pos = 0;
11
+}
12
+
13
+void DynBuf_SeekToBeg(CDynBuf *p)
14
+{
15
+  p->pos = 0;
16
+}
17
+
18
+int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc)
19
+{
20
+  if (size > p->size - p->pos)
21
+  {
22
+    size_t newSize = p->pos + size;
23
+    Byte *data;
24
+    newSize += newSize / 4;
25
+    data = (Byte *)alloc->Alloc(alloc, newSize);
26
+    if (data == 0)
27
+      return 0;
28
+    p->size = newSize;
29
+    memcpy(data, p->data, p->pos);
30
+    alloc->Free(alloc, p->data);
31
+    p->data = data;
32
+  }
33
+  memcpy(p->data + p->pos, buf, size);
34
+  p->pos += size;
35
+  return 1;
36
+}
37
+
38
+void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc)
39
+{
40
+  alloc->Free(alloc, p->data);
41
+  p->data = 0;
42
+  p->size = 0;
43
+  p->pos = 0;
44
+}
... ...
@@ -1,24 +1,23 @@
1 1
 /* 7zCrc.c -- CRC32 calculation
2
-2008-08-05
3
-Igor Pavlov
4
-Public domain */
2
+2009-11-23 : Igor Pavlov : Public domain */
5 3
 
6 4
 #include "7zCrc.h"
5
+#include "CpuArch.h"
7 6
 
8
-#define kCrcPoly 0xEDB88320
9
-/* aCaB - Make the table a global const */
10
-const UInt32 g_CrcTable[256] = { 0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
7
+const UInt32 g_CrcTable[256] = { 0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
11 8
 
12 9
 
10
+#define CRC_UPDATE_BYTE_2(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
11
+
13 12
 UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
14 13
 {
15 14
   const Byte *p = (const Byte *)data;
16
-  for (; size > 0 ; size--, p++)
17
-    v = CRC_UPDATE_BYTE(v, *p);
15
+  for (; size > 0; size--, p++)
16
+    v = CRC_UPDATE_BYTE_2(v, *p);
18 17
   return v;
19 18
 }
20 19
 
21 20
 UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
22 21
 {
23
-  return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
22
+  return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;
24 23
 }
... ...
@@ -1,24 +1,18 @@
1 1
 /* 7zCrc.h -- CRC32 calculation
2
-2008-03-13
3
-Igor Pavlov
4
-Public domain */
2
+2009-11-21 : Igor Pavlov : Public domain */
5 3
 
6 4
 #ifndef __7Z_CRC_H
7 5
 #define __7Z_CRC_H
8 6
 
9
-#include <stddef.h>
10
-
11 7
 #include "Types.h"
12 8
 
13
-extern const UInt32 g_CrcTable[];
14
-
15
-void MY_FAST_CALL CrcGenerateTable(void);
9
+EXTERN_C_BEGIN
16 10
 
17 11
 #define CRC_INIT_VAL 0xFFFFFFFF
18
-#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
19
-#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
20 12
 
21 13
 UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
22 14
 UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
23 15
 
16
+EXTERN_C_END
17
+
24 18
 #endif
25 19
new file mode 100644
... ...
@@ -0,0 +1,474 @@
0
+/* 7zDec.c -- Decoding from 7z folder
1
+2010-11-02 : Igor Pavlov : Public domain */
2
+
3
+#include <string.h>
4
+
5
+#define _7ZIP_PPMD_SUPPPORT
6
+
7
+#include "7z.h"
8
+
9
+#include "Bcj2.h"
10
+#include "Bra.h"
11
+#include "CpuArch.h"
12
+#include "LzmaDec.h"
13
+#include "Lzma2Dec.h"
14
+#ifdef _7ZIP_PPMD_SUPPPORT
15
+#include "Ppmd7.h"
16
+#endif
17
+
18
+#define k_Copy 0
19
+#define k_LZMA2 0x21
20
+#define k_LZMA  0x30101
21
+#define k_BCJ   0x03030103
22
+#define k_PPC   0x03030205
23
+#define k_ARM   0x03030501
24
+#define k_ARMT  0x03030701
25
+#define k_SPARC 0x03030805
26
+#define k_BCJ2  0x0303011B
27
+
28
+#ifdef _7ZIP_PPMD_SUPPPORT
29
+
30
+#define k_PPMD 0x30401
31
+
32
+typedef struct
33
+{
34
+  IByteIn p;
35
+  const Byte *cur;
36
+  const Byte *end;
37
+  const Byte *begin;
38
+  UInt64 processed;
39
+  Bool extra;
40
+  SRes res;
41
+  ILookInStream *inStream;
42
+} CByteInToLook;
43
+
44
+static Byte ReadByte(void *pp)
45
+{
46
+  CByteInToLook *p = (CByteInToLook *)pp;
47
+  if (p->cur != p->end)
48
+    return *p->cur++;
49
+  if (p->res == SZ_OK)
50
+  {
51
+    size_t size = p->cur - p->begin;
52
+    p->processed += size;
53
+    p->res = p->inStream->Skip(p->inStream, size);
54
+    size = (1 << 25);
55
+    p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
56
+    p->cur = p->begin;
57
+    p->end = p->begin + size;
58
+    if (size != 0)
59
+      return *p->cur++;;
60
+  }
61
+  p->extra = True;
62
+  return 0;
63
+}
64
+
65
+static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
66
+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
67
+{
68
+  CPpmd7 ppmd;
69
+  CByteInToLook s;
70
+  SRes res = SZ_OK;
71
+
72
+  s.p.Read = ReadByte;
73
+  s.inStream = inStream;
74
+  s.begin = s.end = s.cur = NULL;
75
+  s.extra = False;
76
+  s.res = SZ_OK;
77
+  s.processed = 0;
78
+
79
+  if (coder->Props.size != 5)
80
+    return SZ_ERROR_UNSUPPORTED;
81
+
82
+  {
83
+    unsigned order = coder->Props.data[0];
84
+    UInt32 memSize = GetUi32(coder->Props.data + 1);
85
+    if (order < PPMD7_MIN_ORDER ||
86
+        order > PPMD7_MAX_ORDER ||
87
+        memSize < PPMD7_MIN_MEM_SIZE ||
88
+        memSize > PPMD7_MAX_MEM_SIZE)
89
+      return SZ_ERROR_UNSUPPORTED;
90
+    Ppmd7_Construct(&ppmd);
91
+    if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
92
+      return SZ_ERROR_MEM;
93
+    Ppmd7_Init(&ppmd, order);
94
+  }
95
+  {
96
+    CPpmd7z_RangeDec rc;
97
+    Ppmd7z_RangeDec_CreateVTable(&rc);
98
+    rc.Stream = &s.p;
99
+    if (!Ppmd7z_RangeDec_Init(&rc))
100
+      res = SZ_ERROR_DATA;
101
+    else if (s.extra)
102
+      res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
103
+    else
104
+    {
105
+      SizeT i;
106
+      for (i = 0; i < outSize; i++)
107
+      {
108
+        int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
109
+        if (s.extra || sym < 0)
110
+          break;
111
+        outBuffer[i] = (Byte)sym;
112
+      }
113
+      if (i != outSize)
114
+        res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
115
+      else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
116
+        res = SZ_ERROR_DATA;
117
+    }
118
+  }
119
+  Ppmd7_Free(&ppmd, allocMain);
120
+  return res;
121
+}
122
+
123
+#endif
124
+
125
+
126
+static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
127
+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
128
+{
129
+  CLzmaDec state;
130
+  SRes res = SZ_OK;
131
+
132
+  LzmaDec_Construct(&state);
133
+  RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
134
+  state.dic = outBuffer;
135
+  state.dicBufSize = outSize;
136
+  LzmaDec_Init(&state);
137
+
138
+  for (;;)
139
+  {
140
+    Byte *inBuf = NULL;
141
+    size_t lookahead = (1 << 18);
142
+    if (lookahead > inSize)
143
+      lookahead = (size_t)inSize;
144
+    res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
145
+    if (res != SZ_OK)
146
+      break;
147
+
148
+    {
149
+      SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
150
+      ELzmaStatus status;
151
+      res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
152
+      lookahead -= inProcessed;
153
+      inSize -= inProcessed;
154
+      if (res != SZ_OK)
155
+        break;
156
+      if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
157
+      {
158
+        if (state.dicBufSize != outSize || lookahead != 0 ||
159
+            (status != LZMA_STATUS_FINISHED_WITH_MARK &&
160
+             status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
161
+          res = SZ_ERROR_DATA;
162
+        break;
163
+      }
164
+      res = inStream->Skip((void *)inStream, inProcessed);
165
+      if (res != SZ_OK)
166
+        break;
167
+    }
168
+  }
169
+
170
+  LzmaDec_FreeProbs(&state, allocMain);
171
+  return res;
172
+}
173
+
174
+static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
175
+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
176
+{
177
+  CLzma2Dec state;
178
+  SRes res = SZ_OK;
179
+
180
+  Lzma2Dec_Construct(&state);
181
+  if (coder->Props.size != 1)
182
+    return SZ_ERROR_DATA;
183
+  RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
184
+  state.decoder.dic = outBuffer;
185
+  state.decoder.dicBufSize = outSize;
186
+  Lzma2Dec_Init(&state);
187
+
188
+  for (;;)
189
+  {
190
+    Byte *inBuf = NULL;
191
+    size_t lookahead = (1 << 18);
192
+    if (lookahead > inSize)
193
+      lookahead = (size_t)inSize;
194
+    res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
195
+    if (res != SZ_OK)
196
+      break;
197
+
198
+    {
199
+      SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
200
+      ELzmaStatus status;
201
+      res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
202
+      lookahead -= inProcessed;
203
+      inSize -= inProcessed;
204
+      if (res != SZ_OK)
205
+        break;
206
+      if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
207
+      {
208
+        if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
209
+            (status != LZMA_STATUS_FINISHED_WITH_MARK))
210
+          res = SZ_ERROR_DATA;
211
+        break;
212
+      }
213
+      res = inStream->Skip((void *)inStream, inProcessed);
214
+      if (res != SZ_OK)
215
+        break;
216
+    }
217
+  }
218
+
219
+  Lzma2Dec_FreeProbs(&state, allocMain);
220
+  return res;
221
+}
222
+
223
+static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
224
+{
225
+  while (inSize > 0)
226
+  {
227
+    void *inBuf;
228
+    size_t curSize = (1 << 18);
229
+    if (curSize > inSize)
230
+      curSize = (size_t)inSize;
231
+    RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
232
+    if (curSize == 0)
233
+      return SZ_ERROR_INPUT_EOF;
234
+    memcpy(outBuffer, inBuf, curSize);
235
+    outBuffer += curSize;
236
+    inSize -= curSize;
237
+    RINOK(inStream->Skip((void *)inStream, curSize));
238
+  }
239
+  return SZ_OK;
240
+}
241
+
242
+static Bool IS_MAIN_METHOD(UInt32 m)
243
+{
244
+  switch(m)
245
+  {
246
+    case k_Copy:
247
+    case k_LZMA:
248
+    case k_LZMA2:
249
+    #ifdef _7ZIP_PPMD_SUPPPORT
250
+    case k_PPMD:
251
+    #endif
252
+      return True;
253
+  }
254
+  return False;
255
+}
256
+
257
+static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
258
+{
259
+  return
260
+      c->NumInStreams == 1 &&
261
+      c->NumOutStreams == 1 &&
262
+      c->MethodID <= (UInt32)0xFFFFFFFF &&
263
+      IS_MAIN_METHOD((UInt32)c->MethodID);
264
+}
265
+
266
+#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
267
+
268
+static SRes CheckSupportedFolder(const CSzFolder *f)
269
+{
270
+  if (f->NumCoders < 1 || f->NumCoders > 4)
271
+    return SZ_ERROR_UNSUPPORTED;
272
+
273
+  if (f->Coders[0].MethodID == 0x06F10701) /* ACAB */
274
+    return SZ_ERROR_ENCRYPTED;
275
+
276
+  if (!IS_SUPPORTED_CODER(&f->Coders[0]))
277
+    return SZ_ERROR_UNSUPPORTED;
278
+  if (f->NumCoders == 1)
279
+  {
280
+    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
281
+      return SZ_ERROR_UNSUPPORTED;
282
+    return SZ_OK;
283
+  }
284
+  if (f->NumCoders == 2)
285
+  {
286
+    CSzCoderInfo *c = &f->Coders[1];
287
+    if (c->MethodID > (UInt32)0xFFFFFFFF ||
288
+        c->NumInStreams != 1 ||
289
+        c->NumOutStreams != 1 ||
290
+        f->NumPackStreams != 1 ||
291
+        f->PackStreams[0] != 0 ||
292
+        f->NumBindPairs != 1 ||
293
+        f->BindPairs[0].InIndex != 1 ||
294
+        f->BindPairs[0].OutIndex != 0)
295
+      return SZ_ERROR_UNSUPPORTED;
296
+    switch ((UInt32)c->MethodID)
297
+    {
298
+      case k_BCJ:
299
+      case k_ARM:
300
+        break;
301
+      default:
302
+        return SZ_ERROR_UNSUPPORTED;
303
+    }
304
+    return SZ_OK;
305
+  }
306
+  if (f->NumCoders == 4)
307
+  {
308
+    if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
309
+        !IS_SUPPORTED_CODER(&f->Coders[2]) ||
310
+        !IS_BCJ2(&f->Coders[3]))
311
+      return SZ_ERROR_UNSUPPORTED;
312
+    if (f->NumPackStreams != 4 ||
313
+        f->PackStreams[0] != 2 ||
314
+        f->PackStreams[1] != 6 ||
315
+        f->PackStreams[2] != 1 ||
316
+        f->PackStreams[3] != 0 ||
317
+        f->NumBindPairs != 3 ||
318
+        f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
319
+        f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
320
+        f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
321
+      return SZ_ERROR_UNSUPPORTED;
322
+    return SZ_OK;
323
+  }
324
+  return SZ_ERROR_UNSUPPORTED;
325
+}
326
+
327
+static UInt64 GetSum(const UInt64 *values, UInt32 index)
328
+{
329
+  UInt64 sum = 0;
330
+  UInt32 i;
331
+  for (i = 0; i < index; i++)
332
+    sum += values[i];
333
+  return sum;
334
+}
335
+
336
+#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
337
+
338
+static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
339
+    ILookInStream *inStream, UInt64 startPos,
340
+    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
341
+    Byte *tempBuf[])
342
+{
343
+  UInt32 ci;
344
+  SizeT tempSizes[3] = { 0, 0, 0};
345
+  SizeT tempSize3 = 0;
346
+  Byte *tempBuf3 = 0;
347
+
348
+  RINOK(CheckSupportedFolder(folder));
349
+
350
+  for (ci = 0; ci < folder->NumCoders; ci++)
351
+  {
352
+    CSzCoderInfo *coder = &folder->Coders[ci];
353
+
354
+    if (IS_MAIN_METHOD((UInt32)coder->MethodID))
355
+    {
356
+      UInt32 si = 0;
357
+      UInt64 offset;
358
+      UInt64 inSize;
359
+      Byte *outBufCur = outBuffer;
360
+      SizeT outSizeCur = outSize;
361
+      if (folder->NumCoders == 4)
362
+      {
363
+        UInt32 indices[] = { 3, 2, 0 };
364
+        UInt64 unpackSize = folder->UnpackSizes[ci];
365
+        si = indices[ci];
366
+        if (ci < 2)
367
+        {
368
+          Byte *temp;
369
+          outSizeCur = (SizeT)unpackSize;
370
+          if (outSizeCur != unpackSize)
371
+            return SZ_ERROR_MEM;
372
+          temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
373
+          if (temp == 0 && outSizeCur != 0)
374
+            return SZ_ERROR_MEM;
375
+          outBufCur = tempBuf[1 - ci] = temp;
376
+          tempSizes[1 - ci] = outSizeCur;
377
+        }
378
+        else if (ci == 2)
379
+        {
380
+          if (unpackSize > outSize) /* check it */
381
+            return SZ_ERROR_PARAM;
382
+          tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
383
+          tempSize3 = outSizeCur = (SizeT)unpackSize;
384
+        }
385
+        else
386
+          return SZ_ERROR_UNSUPPORTED;
387
+      }
388
+      offset = GetSum(packSizes, si);
389
+      inSize = packSizes[si];
390
+      RINOK(LookInStream_SeekTo(inStream, startPos + offset));
391
+
392
+      if (coder->MethodID == k_Copy)
393
+      {
394
+        if (inSize != outSizeCur) /* check it */
395
+          return SZ_ERROR_DATA;
396
+        RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
397
+      }
398
+      else if (coder->MethodID == k_LZMA)
399
+      {
400
+        RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
401
+      }
402
+      else if (coder->MethodID == k_LZMA2)
403
+      {
404
+        RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
405
+      }
406
+      else
407
+      {
408
+        #ifdef _7ZIP_PPMD_SUPPPORT
409
+        RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
410
+        #else
411
+        return SZ_ERROR_UNSUPPORTED;
412
+        #endif
413
+      }
414
+    }
415
+    else if (coder->MethodID == k_BCJ2)
416
+    {
417
+      UInt64 offset = GetSum(packSizes, 1);
418
+      UInt64 s3Size = packSizes[1];
419
+      SRes res;
420
+      if (ci != 3)
421
+        return SZ_ERROR_UNSUPPORTED;
422
+      RINOK(LookInStream_SeekTo(inStream, startPos + offset));
423
+      tempSizes[2] = (SizeT)s3Size;
424
+      if (tempSizes[2] != s3Size)
425
+        return SZ_ERROR_MEM;
426
+      tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
427
+      if (tempBuf[2] == 0 && tempSizes[2] != 0)
428
+        return SZ_ERROR_MEM;
429
+      res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
430
+      RINOK(res)
431
+
432
+      res = Bcj2_Decode(
433
+          tempBuf3, tempSize3,
434
+          tempBuf[0], tempSizes[0],
435
+          tempBuf[1], tempSizes[1],
436
+          tempBuf[2], tempSizes[2],
437
+          outBuffer, outSize);
438
+      RINOK(res)
439
+    }
440
+    else
441
+    {
442
+      if (ci != 1)
443
+        return SZ_ERROR_UNSUPPORTED;
444
+      switch(coder->MethodID)
445
+      {
446
+        case k_BCJ:
447
+        {
448
+          UInt32 state;
449
+          x86_Convert_Init(state);
450
+          x86_Convert(outBuffer, outSize, 0, &state, 0);
451
+          break;
452
+        }
453
+        CASE_BRA_CONV(ARM)
454
+        default:
455
+          return SZ_ERROR_UNSUPPORTED;
456
+      }
457
+    }
458
+  }
459
+  return SZ_OK;
460
+}
461
+
462
+SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
463
+    ILookInStream *inStream, UInt64 startPos,
464
+    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
465
+{
466
+  Byte *tempBuf[3] = { 0, 0, 0};
467
+  int i;
468
+  SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,
469
+      outBuffer, (SizeT)outSize, allocMain, tempBuf);
470
+  for (i = 0; i < 3; i++)
471
+    IAlloc_Free(allocMain, tempBuf[i]);
472
+  return res;
473
+}
... ...
@@ -1,15 +1,15 @@
1 1
 /* 7zFile.c -- File IO
2
-2008-11-22 : Igor Pavlov : Public domain */
2
+2009-11-24 : Igor Pavlov : Public domain */
3 3
 
4 4
 #include "7zFile.h"
5 5
 
6 6
 #ifndef USE_WINDOWS_FILE
7 7
 
8
+#ifndef UNDER_CE
8 9
 #include <errno.h>
9
-
10 10
 #endif
11 11
 
12
-#ifdef USE_WINDOWS_FILE
12
+#else
13 13
 
14 14
 /*
15 15
    ReadFile and WriteFile functions in Windows have BUG:
... ...
@@ -34,6 +34,7 @@ void File_Construct(CSzFile *p)
34 34
   #endif
35 35
 }
36 36
 
37
+#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
37 38
 static WRes File_Open(CSzFile *p, const char *name, int writeMode)
38 39
 {
39 40
   #ifdef USE_WINDOWS_FILE
... ...
@@ -45,12 +46,32 @@ static WRes File_Open(CSzFile *p, const char *name, int writeMode)
45 45
   return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
46 46
   #else
47 47
   p->file = fopen(name, writeMode ? "wb+" : "rb");
48
-  return (p->file != 0) ? 0 : errno;
48
+  return (p->file != 0) ? 0 :
49
+    #ifdef UNDER_CE
50
+    2; /* ENOENT */
51
+    #else
52
+    errno;
53
+    #endif
49 54
   #endif
50 55
 }
51 56
 
52 57
 WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
53 58
 WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
59
+#endif
60
+
61
+#ifdef USE_WINDOWS_FILE
62
+static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
63
+{
64
+  p->handle = CreateFileW(name,
65
+      writeMode ? GENERIC_WRITE : GENERIC_READ,
66
+      FILE_SHARE_READ, NULL,
67
+      writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
68
+      FILE_ATTRIBUTE_NORMAL, NULL);
69
+  return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
70
+}
71
+WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
72
+WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
73
+#endif
54 74
 
55 75
 WRes File_Close(CSzFile *p)
56 76
 {
... ...
@@ -1,14 +1,12 @@
1 1
 /* 7zFile.h -- File IO
2
-2008-11-22 : Igor Pavlov : Public domain */
2
+2009-11-24 : Igor Pavlov : Public domain */
3 3
 
4 4
 #ifndef __7Z_FILE_H
5 5
 #define __7Z_FILE_H
6 6
 
7
-/* aCaB -- do not use HANDLE on win32
8 7
 #ifdef _WIN32
9 8
 #define USE_WINDOWS_FILE
10 9
 #endif
11
-*/
12 10
 
13 11
 #ifdef USE_WINDOWS_FILE
14 12
 #include <windows.h>
... ...
@@ -18,21 +16,29 @@
18 18
 
19 19
 #include "Types.h"
20 20
 
21
+EXTERN_C_BEGIN
21 22
 
22 23
 /* ---------- File ---------- */
23 24
 
24 25
 typedef struct
25 26
 {
26
-  #ifdef USE_WINDOWS_FILE
27
+#ifdef USE_WINDOWS_FILE
27 28
   HANDLE handle;
28
-  #else
29
+#else
29 30
   FILE *file;
30
-  #endif
31
+#endif
32
+    fmap_t *fmap;
31 33
 } CSzFile;
32 34
 
33 35
 void File_Construct(CSzFile *p);
36
+#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
34 37
 WRes InFile_Open(CSzFile *p, const char *name);
35 38
 WRes OutFile_Open(CSzFile *p, const char *name);
39
+#endif
40
+#ifdef USE_WINDOWS_FILE
41
+WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
42
+WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
43
+#endif
36 44
 WRes File_Close(CSzFile *p);
37 45
 
38 46
 /* reads max(*size, remain file's size) bytes */
... ...
@@ -73,4 +79,6 @@ typedef struct
73 73
 
74 74
 void FileOutStream_CreateVTable(CFileOutStream *p);
75 75
 
76
+EXTERN_C_END
77
+
76 78
 #endif
77 79
new file mode 100644
... ...
@@ -0,0 +1,1402 @@
0
+/* 7zIn.c -- 7z Input functions
1
+2010-10-29 : Igor Pavlov : Public domain */
2
+
3
+#include <string.h>
4
+
5
+#include "7z.h"
6
+#include "7zCrc.h"
7
+#include "CpuArch.h"
8
+
9
+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
10
+
11
+#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; }
12
+
13
+#define NUM_FOLDER_CODERS_MAX 32
14
+#define NUM_CODER_STREAMS_MAX 32
15
+
16
+void SzCoderInfo_Init(CSzCoderInfo *p)
17
+{
18
+  Buf_Init(&p->Props);
19
+}
20
+
21
+void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
22
+{
23
+  Buf_Free(&p->Props, alloc);
24
+  SzCoderInfo_Init(p);
25
+}
26
+
27
+void SzFolder_Init(CSzFolder *p)
28
+{
29
+  p->Coders = 0;
30
+  p->BindPairs = 0;
31
+  p->PackStreams = 0;
32
+  p->UnpackSizes = 0;
33
+  p->NumCoders = 0;
34
+  p->NumBindPairs = 0;
35
+  p->NumPackStreams = 0;
36
+  p->UnpackCRCDefined = 0;
37
+  p->UnpackCRC = 0;
38
+  p->NumUnpackStreams = 0;
39
+}
40
+
41
+void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
42
+{
43
+  UInt32 i;
44
+  if (p->Coders)
45
+    for (i = 0; i < p->NumCoders; i++)
46
+      SzCoderInfo_Free(&p->Coders[i], alloc);
47
+  IAlloc_Free(alloc, p->Coders);
48
+  IAlloc_Free(alloc, p->BindPairs);
49
+  IAlloc_Free(alloc, p->PackStreams);
50
+  IAlloc_Free(alloc, p->UnpackSizes);
51
+  SzFolder_Init(p);
52
+}
53
+
54
+UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
55
+{
56
+  UInt32 result = 0;
57
+  UInt32 i;
58
+  for (i = 0; i < p->NumCoders; i++)
59
+    result += p->Coders[i].NumOutStreams;
60
+  return result;
61
+}
62
+
63
+int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
64
+{
65
+  UInt32 i;
66
+  for (i = 0; i < p->NumBindPairs; i++)
67
+    if (p->BindPairs[i].InIndex == inStreamIndex)
68
+      return i;
69
+  return -1;
70
+}
71
+
72
+
73
+int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
74
+{
75
+  UInt32 i;
76
+  for (i = 0; i < p->NumBindPairs; i++)
77
+    if (p->BindPairs[i].OutIndex == outStreamIndex)
78
+      return i;
79
+  return -1;
80
+}
81
+
82
+UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
83
+{
84
+  int i = (int)SzFolder_GetNumOutStreams(p);
85
+  if (i == 0)
86
+    return 0;
87
+  for (i--; i >= 0; i--)
88
+    if (SzFolder_FindBindPairForOutStream(p, i) < 0)
89
+      return p->UnpackSizes[i];
90
+  /* throw 1; */
91
+  return 0;
92
+}
93
+
94
+void SzFile_Init(CSzFileItem *p)
95
+{
96
+  p->HasStream = 1;
97
+  p->IsDir = 0;
98
+  p->IsAnti = 0;
99
+  p->CrcDefined = 0;
100
+  p->MTimeDefined = 0;
101
+}
102
+
103
+void SzAr_Init(CSzAr *p)
104
+{
105
+  p->PackSizes = 0;
106
+  p->PackCRCsDefined = 0;
107
+  p->PackCRCs = 0;
108
+  p->Folders = 0;
109
+  p->Files = 0;
110
+  p->NumPackStreams = 0;
111
+  p->NumFolders = 0;
112
+  p->NumFiles = 0;
113
+}
114
+
115
+void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
116
+{
117
+  UInt32 i;
118
+  if (p->Folders)
119
+    for (i = 0; i < p->NumFolders; i++)
120
+      SzFolder_Free(&p->Folders[i], alloc);
121
+
122
+  IAlloc_Free(alloc, p->PackSizes);
123
+  IAlloc_Free(alloc, p->PackCRCsDefined);
124
+  IAlloc_Free(alloc, p->PackCRCs);
125
+  IAlloc_Free(alloc, p->Folders);
126
+  IAlloc_Free(alloc, p->Files);
127
+  SzAr_Init(p);
128
+}
129
+
130
+
131
+void SzArEx_Init(CSzArEx *p)
132
+{
133
+  SzAr_Init(&p->db);
134
+  p->FolderStartPackStreamIndex = 0;
135
+  p->PackStreamStartPositions = 0;
136
+  p->FolderStartFileIndex = 0;
137
+  p->FileIndexToFolderIndexMap = 0;
138
+  p->FileNameOffsets = 0;
139
+  Buf_Init(&p->FileNames);
140
+}
141
+
142
+void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
143
+{
144
+  IAlloc_Free(alloc, p->FolderStartPackStreamIndex);
145
+  IAlloc_Free(alloc, p->PackStreamStartPositions);
146
+  IAlloc_Free(alloc, p->FolderStartFileIndex);
147
+  IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);
148
+
149
+  IAlloc_Free(alloc, p->FileNameOffsets);
150
+  Buf_Free(&p->FileNames, alloc);
151
+
152
+  SzAr_Free(&p->db, alloc);
153
+  SzArEx_Init(p);
154
+}
155
+
156
+/*
157
+UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
158
+{
159
+  return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
160
+}
161
+
162
+UInt64 GetFilePackSize(int fileIndex) const
163
+{
164
+  int folderIndex = FileIndexToFolderIndexMap[fileIndex];
165
+  if (folderIndex >= 0)
166
+  {
167
+    const CSzFolder &folderInfo = Folders[folderIndex];
168
+    if (FolderStartFileIndex[folderIndex] == fileIndex)
169
+    return GetFolderFullPackSize(folderIndex);
170
+  }
171
+  return 0;
172
+}
173
+*/
174
+
175
+#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \
176
+  if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; }
177
+
178
+static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc)
179
+{
180
+  UInt32 startPos = 0;
181
+  UInt64 startPosSize = 0;
182
+  UInt32 i;
183
+  UInt32 folderIndex = 0;
184
+  UInt32 indexInFolder = 0;
185
+  MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc);
186
+  for (i = 0; i < p->db.NumFolders; i++)
187
+  {
188
+    p->FolderStartPackStreamIndex[i] = startPos;
189
+    startPos += p->db.Folders[i].NumPackStreams;
190
+  }
191
+
192
+  MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc);
193
+
194
+  for (i = 0; i < p->db.NumPackStreams; i++)
195
+  {
196
+    p->PackStreamStartPositions[i] = startPosSize;
197
+    startPosSize += p->db.PackSizes[i];
198
+  }
199
+
200
+  MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc);
201
+  MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc);
202
+
203
+  for (i = 0; i < p->db.NumFiles; i++)
204
+  {
205
+    CSzFileItem *file = p->db.Files + i;
206
+    int emptyStream = !file->HasStream;
207
+    if (emptyStream && indexInFolder == 0)
208
+    {
209
+      p->FileIndexToFolderIndexMap[i] = (UInt32)-1;
210
+      continue;
211
+    }
212
+    if (indexInFolder == 0)
213
+    {
214
+      /*
215
+      v3.13 incorrectly worked with empty folders
216
+      v4.07: Loop for skipping empty folders
217
+      */
218
+      for (;;)
219
+      {
220
+        if (folderIndex >= p->db.NumFolders)
221
+          return SZ_ERROR_ARCHIVE;
222
+        p->FolderStartFileIndex[folderIndex] = i;
223
+        if (p->db.Folders[folderIndex].NumUnpackStreams != 0)
224
+          break;
225
+        folderIndex++;
226
+      }
227
+    }
228
+    p->FileIndexToFolderIndexMap[i] = folderIndex;
229
+    if (emptyStream)
230
+      continue;
231
+    indexInFolder++;
232
+    if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams)
233
+    {
234
+      folderIndex++;
235
+      indexInFolder = 0;
236
+    }
237
+  }
238
+  return SZ_OK;
239
+}
240
+
241
+
242
+UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder)
243
+{
244
+  return p->dataPos +
245
+    p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
246
+}
247
+
248
+int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize)
249
+{
250
+  UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex];
251
+  CSzFolder *folder = p->db.Folders + folderIndex;
252
+  UInt64 size = 0;
253
+  UInt32 i;
254
+  for (i = 0; i < folder->NumPackStreams; i++)
255
+  {
256
+    UInt64 t = size + p->db.PackSizes[packStreamIndex + i];
257
+    if (t < size) /* check it */
258
+      return SZ_ERROR_FAIL;
259
+    size = t;
260
+  }
261
+  *resSize = size;
262
+  return SZ_OK;
263
+}
264
+
265
+
266
+/*
267
+SRes SzReadTime(const CObjectVector<CBuf> &dataVector,
268
+    CObjectVector<CSzFileItem> &files, UInt64 type)
269
+{
270
+  CBoolVector boolVector;
271
+  RINOK(ReadBoolVector2(files.Size(), boolVector))
272
+
273
+  CStreamSwitch streamSwitch;
274
+  RINOK(streamSwitch.Set(this, &dataVector));
275
+
276
+  for (int i = 0; i < files.Size(); i++)
277
+  {
278
+    CSzFileItem &file = files[i];
279
+    CArchiveFileTime fileTime;
280
+    bool defined = boolVector[i];
281
+    if (defined)
282
+    {
283
+      UInt32 low, high;
284
+      RINOK(SzReadUInt32(low));
285
+      RINOK(SzReadUInt32(high));
286
+      fileTime.dwLowDateTime = low;
287
+      fileTime.dwHighDateTime = high;
288
+    }
289
+    switch(type)
290
+    {
291
+      case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break;
292
+      case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break;
293
+      case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break;
294
+    }
295
+  }
296
+  return SZ_OK;
297
+}
298
+*/
299
+
300
+static int TestSignatureCandidate(Byte *testBytes)
301
+{
302
+  size_t i;
303
+  for (i = 0; i < k7zSignatureSize; i++)
304
+    if (testBytes[i] != k7zSignature[i])
305
+      return 0;
306
+  return 1;
307
+}
308
+
309
+typedef struct _CSzState
310
+{
311
+  Byte *Data;
312
+  size_t Size;
313
+}CSzData;
314
+
315
+static SRes SzReadByte(CSzData *sd, Byte *b)
316
+{
317
+  if (sd->Size == 0)
318
+    return SZ_ERROR_ARCHIVE;
319
+  sd->Size--;
320
+  *b = *sd->Data++;
321
+  return SZ_OK;
322
+}
323
+
324
+static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size)
325
+{
326
+  size_t i;
327
+  for (i = 0; i < size; i++)
328
+  {
329
+    RINOK(SzReadByte(sd, data + i));
330
+  }
331
+  return SZ_OK;
332
+}
333
+
334
+static SRes SzReadUInt32(CSzData *sd, UInt32 *value)
335
+{
336
+  int i;
337
+  *value = 0;
338
+  for (i = 0; i < 4; i++)
339
+  {
340
+    Byte b;
341
+    RINOK(SzReadByte(sd, &b));
342
+    *value |= ((UInt32)(b) << (8 * i));
343
+  }
344
+  return SZ_OK;
345
+}
346
+
347
+static SRes SzReadNumber(CSzData *sd, UInt64 *value)
348
+{
349
+  Byte firstByte;
350
+  Byte mask = 0x80;
351
+  int i;
352
+  RINOK(SzReadByte(sd, &firstByte));
353
+  *value = 0;
354
+  for (i = 0; i < 8; i++)
355
+  {
356
+    Byte b;
357
+    if ((firstByte & mask) == 0)
358
+    {
359
+      UInt64 highPart = firstByte & (mask - 1);
360
+      *value += (highPart << (8 * i));
361
+      return SZ_OK;
362
+    }
363
+    RINOK(SzReadByte(sd, &b));
364
+    *value |= ((UInt64)b << (8 * i));
365
+    mask >>= 1;
366
+  }
367
+  return SZ_OK;
368
+}
369
+
370
+static SRes SzReadNumber32(CSzData *sd, UInt32 *value)
371
+{
372
+  UInt64 value64;
373
+  RINOK(SzReadNumber(sd, &value64));
374
+  if (value64 >= 0x80000000)
375
+    return SZ_ERROR_UNSUPPORTED;
376
+  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
377
+    return SZ_ERROR_UNSUPPORTED;
378
+  *value = (UInt32)value64;
379
+  return SZ_OK;
380
+}
381
+
382
+static SRes SzReadID(CSzData *sd, UInt64 *value)
383
+{
384
+  return SzReadNumber(sd, value);
385
+}
386
+
387
+static SRes SzSkeepDataSize(CSzData *sd, UInt64 size)
388
+{
389
+  if (size > sd->Size)
390
+    return SZ_ERROR_ARCHIVE;
391
+  sd->Size -= (size_t)size;
392
+  sd->Data += (size_t)size;
393
+  return SZ_OK;
394
+}
395
+
396
+static SRes SzSkeepData(CSzData *sd)
397
+{
398
+  UInt64 size;
399
+  RINOK(SzReadNumber(sd, &size));
400
+  return SzSkeepDataSize(sd, size);
401
+}
402
+
403
+static SRes SzReadArchiveProperties(CSzData *sd)
404
+{
405
+  for (;;)
406
+  {
407
+    UInt64 type;
408
+    RINOK(SzReadID(sd, &type));
409
+    if (type == k7zIdEnd)
410
+      break;
411
+    SzSkeepData(sd);
412
+  }
413
+  return SZ_OK;
414
+}
415
+
416
+static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute)
417
+{
418
+  for (;;)
419
+  {
420
+    UInt64 type;
421
+    RINOK(SzReadID(sd, &type));
422
+    if (type == attribute)
423
+      return SZ_OK;
424
+    if (type == k7zIdEnd)
425
+      return SZ_ERROR_ARCHIVE;
426
+    RINOK(SzSkeepData(sd));
427
+  }
428
+}
429
+
430
+static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)
431
+{
432
+  Byte b = 0;
433
+  Byte mask = 0;
434
+  size_t i;
435
+  MY_ALLOC(Byte, *v, numItems, alloc);
436
+  for (i = 0; i < numItems; i++)
437
+  {
438
+    if (mask == 0)
439
+    {
440
+      RINOK(SzReadByte(sd, &b));
441
+      mask = 0x80;
442
+    }
443
+    (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);
444
+    mask >>= 1;
445
+  }
446
+  return SZ_OK;
447
+}
448
+
449
+static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)
450
+{
451
+  Byte allAreDefined;
452
+  size_t i;
453
+  RINOK(SzReadByte(sd, &allAreDefined));
454
+  if (allAreDefined == 0)
455
+    return SzReadBoolVector(sd, numItems, v, alloc);
456
+  MY_ALLOC(Byte, *v, numItems, alloc);
457
+  for (i = 0; i < numItems; i++)
458
+    (*v)[i] = 1;
459
+  return SZ_OK;
460
+}
461
+
462
+static SRes SzReadHashDigests(
463
+    CSzData *sd,
464
+    size_t numItems,
465
+    Byte **digestsDefined,
466
+    UInt32 **digests,
467
+    ISzAlloc *alloc)
468
+{
469
+  size_t i;
470
+  RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc));
471
+  MY_ALLOC(UInt32, *digests, numItems, alloc);
472
+  for (i = 0; i < numItems; i++)
473
+    if ((*digestsDefined)[i])
474
+    {
475
+      RINOK(SzReadUInt32(sd, (*digests) + i));
476
+    }
477
+  return SZ_OK;
478
+}
479
+
480
+static SRes SzReadPackInfo(
481
+    CSzData *sd,
482
+    UInt64 *dataOffset,
483
+    UInt32 *numPackStreams,
484
+    UInt64 **packSizes,
485
+    Byte **packCRCsDefined,
486
+    UInt32 **packCRCs,
487
+    ISzAlloc *alloc)
488
+{
489
+  UInt32 i;
490
+  RINOK(SzReadNumber(sd, dataOffset));
491
+  RINOK(SzReadNumber32(sd, numPackStreams));
492
+
493
+  RINOK(SzWaitAttribute(sd, k7zIdSize));
494
+
495
+  MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc);
496
+
497
+  for (i = 0; i < *numPackStreams; i++)
498
+  {
499
+    RINOK(SzReadNumber(sd, (*packSizes) + i));
500
+  }
501
+
502
+  for (;;)
503
+  {
504
+    UInt64 type;
505
+    RINOK(SzReadID(sd, &type));
506
+    if (type == k7zIdEnd)
507
+      break;
508
+    if (type == k7zIdCRC)
509
+    {
510
+      RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc));
511
+      continue;
512
+    }
513
+    RINOK(SzSkeepData(sd));
514
+  }
515
+  if (*packCRCsDefined == 0)
516
+  {
517
+    MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc);
518
+    MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc);
519
+    for (i = 0; i < *numPackStreams; i++)
520
+    {
521
+      (*packCRCsDefined)[i] = 0;
522
+      (*packCRCs)[i] = 0;
523
+    }
524
+  }
525
+  return SZ_OK;
526
+}
527
+
528
+static SRes SzReadSwitch(CSzData *sd)
529
+{
530
+  Byte external;
531
+  RINOK(SzReadByte(sd, &external));
532
+  return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
533
+}
534
+
535
+static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)
536
+{
537
+  UInt32 numCoders, numBindPairs, numPackStreams, i;
538
+  UInt32 numInStreams = 0, numOutStreams = 0;
539
+  
540
+  RINOK(SzReadNumber32(sd, &numCoders));
541
+  if (numCoders > NUM_FOLDER_CODERS_MAX)
542
+    return SZ_ERROR_UNSUPPORTED;
543
+  folder->NumCoders = numCoders;
544
+  
545
+  MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc);
546
+
547
+  for (i = 0; i < numCoders; i++)
548
+    SzCoderInfo_Init(folder->Coders + i);
549
+
550
+  for (i = 0; i < numCoders; i++)
551
+  {
552
+    Byte mainByte;
553
+    CSzCoderInfo *coder = folder->Coders + i;
554
+    {
555
+      unsigned idSize, j;
556
+      Byte longID[15];
557
+      RINOK(SzReadByte(sd, &mainByte));
558
+      idSize = (unsigned)(mainByte & 0xF);
559
+      RINOK(SzReadBytes(sd, longID, idSize));
560
+      if (idSize > sizeof(coder->MethodID))
561
+        return SZ_ERROR_UNSUPPORTED;
562
+      coder->MethodID = 0;
563
+      for (j = 0; j < idSize; j++)
564
+        coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j);
565
+
566
+      if ((mainByte & 0x10) != 0)
567
+      {
568
+        RINOK(SzReadNumber32(sd, &coder->NumInStreams));
569
+        RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
570
+        if (coder->NumInStreams > NUM_CODER_STREAMS_MAX ||
571
+            coder->NumOutStreams > NUM_CODER_STREAMS_MAX)
572
+          return SZ_ERROR_UNSUPPORTED;
573
+      }
574
+      else
575
+      {
576
+        coder->NumInStreams = 1;
577
+        coder->NumOutStreams = 1;
578
+      }
579
+      if ((mainByte & 0x20) != 0)
580
+      {
581
+        UInt64 propertiesSize = 0;
582
+        RINOK(SzReadNumber(sd, &propertiesSize));
583
+        if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc))
584
+          return SZ_ERROR_MEM;
585
+        RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize));
586
+      }
587
+    }
588
+    while ((mainByte & 0x80) != 0)
589
+    {
590
+      RINOK(SzReadByte(sd, &mainByte));
591
+      RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
592
+      if ((mainByte & 0x10) != 0)
593
+      {
594
+        UInt32 n;
595
+        RINOK(SzReadNumber32(sd, &n));
596
+        RINOK(SzReadNumber32(sd, &n));
597
+      }
598
+      if ((mainByte & 0x20) != 0)
599
+      {
600
+        UInt64 propertiesSize = 0;
601
+        RINOK(SzReadNumber(sd, &propertiesSize));
602
+        RINOK(SzSkeepDataSize(sd, propertiesSize));
603
+      }
604
+    }
605
+    numInStreams += coder->NumInStreams;
606
+    numOutStreams += coder->NumOutStreams;
607
+  }
608
+
609
+  if (numOutStreams == 0)
610
+    return SZ_ERROR_UNSUPPORTED;
611
+
612
+  folder->NumBindPairs = numBindPairs = numOutStreams - 1;
613
+  MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);
614
+
615
+  for (i = 0; i < numBindPairs; i++)
616
+  {
617
+    CSzBindPair *bp = folder->BindPairs + i;
618
+    RINOK(SzReadNumber32(sd, &bp->InIndex));
619
+    RINOK(SzReadNumber32(sd, &bp->OutIndex));
620
+  }
621
+
622
+  if (numInStreams < numBindPairs)
623
+    return SZ_ERROR_UNSUPPORTED;
624
+
625
+  folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs;
626
+  MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc);
627
+
628
+  if (numPackStreams == 1)
629
+  {
630
+    for (i = 0; i < numInStreams ; i++)
631
+      if (SzFolder_FindBindPairForInStream(folder, i) < 0)
632
+        break;
633
+    if (i == numInStreams)
634
+      return SZ_ERROR_UNSUPPORTED;
635
+    folder->PackStreams[0] = i;
636
+  }
637
+  else
638
+    for (i = 0; i < numPackStreams; i++)
639
+    {
640
+      RINOK(SzReadNumber32(sd, folder->PackStreams + i));
641
+    }
642
+  return SZ_OK;
643
+}
644
+
645
+static SRes SzReadUnpackInfo(
646
+    CSzData *sd,
647
+    UInt32 *numFolders,
648
+    CSzFolder **folders,  /* for alloc */
649
+    ISzAlloc *alloc,
650
+    ISzAlloc *allocTemp)
651
+{
652
+  UInt32 i;
653
+  RINOK(SzWaitAttribute(sd, k7zIdFolder));
654
+  RINOK(SzReadNumber32(sd, numFolders));
655
+  {
656
+    RINOK(SzReadSwitch(sd));
657
+
658
+    MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc);
659
+
660
+    for (i = 0; i < *numFolders; i++)
661
+      SzFolder_Init((*folders) + i);
662
+
663
+    for (i = 0; i < *numFolders; i++)
664
+    {
665
+      RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc));
666
+    }
667
+  }
668
+
669
+  RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize));
670
+
671
+  for (i = 0; i < *numFolders; i++)
672
+  {
673
+    UInt32 j;
674
+    CSzFolder *folder = (*folders) + i;
675
+    UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder);
676
+
677
+    MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc);
678
+
679
+    for (j = 0; j < numOutStreams; j++)
680
+    {
681
+      RINOK(SzReadNumber(sd, folder->UnpackSizes + j));
682
+    }
683
+  }
684
+
685
+  for (;;)
686
+  {
687
+    UInt64 type;
688
+    RINOK(SzReadID(sd, &type));
689
+    if (type == k7zIdEnd)
690
+      return SZ_OK;
691
+    if (type == k7zIdCRC)
692
+    {
693
+      SRes res;
694
+      Byte *crcsDefined = 0;
695
+      UInt32 *crcs = 0;
696
+      res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp);
697
+      if (res == SZ_OK)
698
+      {
699
+        for (i = 0; i < *numFolders; i++)
700
+        {
701
+          CSzFolder *folder = (*folders) + i;
702
+          folder->UnpackCRCDefined = crcsDefined[i];
703
+          folder->UnpackCRC = crcs[i];
704
+        }
705
+      }
706
+      IAlloc_Free(allocTemp, crcs);
707
+      IAlloc_Free(allocTemp, crcsDefined);
708
+      RINOK(res);
709
+      continue;
710
+    }
711
+    RINOK(SzSkeepData(sd));
712
+  }
713
+}
714
+
715
+static SRes SzReadSubStreamsInfo(
716
+    CSzData *sd,
717
+    UInt32 numFolders,
718
+    CSzFolder *folders,
719
+    UInt32 *numUnpackStreams,
720
+    UInt64 **unpackSizes,
721
+    Byte **digestsDefined,
722
+    UInt32 **digests,
723
+    ISzAlloc *allocTemp)
724
+{
725
+  UInt64 type = 0;
726
+  UInt32 i;
727
+  UInt32 si = 0;
728
+  UInt32 numDigests = 0;
729
+
730
+  for (i = 0; i < numFolders; i++)
731
+    folders[i].NumUnpackStreams = 1;
732
+  *numUnpackStreams = numFolders;
733
+
734
+  for (;;)
735
+  {
736
+    RINOK(SzReadID(sd, &type));
737
+    if (type == k7zIdNumUnpackStream)
738
+    {
739
+      *numUnpackStreams = 0;
740
+      for (i = 0; i < numFolders; i++)
741
+      {
742
+        UInt32 numStreams;
743
+        RINOK(SzReadNumber32(sd, &numStreams));
744
+        folders[i].NumUnpackStreams = numStreams;
745
+        *numUnpackStreams += numStreams;
746
+      }
747
+      continue;
748
+    }
749
+    if (type == k7zIdCRC || type == k7zIdSize)
750
+      break;
751
+    if (type == k7zIdEnd)
752
+      break;
753
+    RINOK(SzSkeepData(sd));
754
+  }
755
+
756
+  if (*numUnpackStreams == 0)
757
+  {
758
+    *unpackSizes = 0;
759
+    *digestsDefined = 0;
760
+    *digests = 0;
761
+  }
762
+  else
763
+  {
764
+    *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64));
765
+    RINOM(*unpackSizes);
766
+    *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte));
767
+    RINOM(*digestsDefined);
768
+    *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32));
769
+    RINOM(*digests);
770
+  }
771
+
772
+  for (i = 0; i < numFolders; i++)
773
+  {
774
+    /*
775
+    v3.13 incorrectly worked with empty folders
776
+    v4.07: we check that folder is empty
777
+    */
778
+    UInt64 sum = 0;
779
+    UInt32 j;
780
+    UInt32 numSubstreams = folders[i].NumUnpackStreams;
781
+    if (numSubstreams == 0)
782
+      continue;
783
+    if (type == k7zIdSize)
784
+    for (j = 1; j < numSubstreams; j++)
785
+    {
786
+      UInt64 size;
787
+      RINOK(SzReadNumber(sd, &size));
788
+      (*unpackSizes)[si++] = size;
789
+      sum += size;
790
+    }
791
+    (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum;
792
+  }
793
+  if (type == k7zIdSize)
794
+  {
795
+    RINOK(SzReadID(sd, &type));
796
+  }
797
+
798
+  for (i = 0; i < *numUnpackStreams; i++)
799
+  {
800
+    (*digestsDefined)[i] = 0;
801
+    (*digests)[i] = 0;
802
+  }
803
+
804
+
805
+  for (i = 0; i < numFolders; i++)
806
+  {
807
+    UInt32 numSubstreams = folders[i].NumUnpackStreams;
808
+    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
809
+      numDigests += numSubstreams;
810
+  }
811
+
812
+ 
813
+  si = 0;
814
+  for (;;)
815
+  {
816
+    if (type == k7zIdCRC)
817
+    {
818
+      int digestIndex = 0;
819
+      Byte *digestsDefined2 = 0;
820
+      UInt32 *digests2 = 0;
821
+      SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp);
822
+      if (res == SZ_OK)
823
+      {
824
+        for (i = 0; i < numFolders; i++)
825
+        {
826
+          CSzFolder *folder = folders + i;
827
+          UInt32 numSubstreams = folder->NumUnpackStreams;
828
+          if (numSubstreams == 1 && folder->UnpackCRCDefined)
829
+          {
830
+            (*digestsDefined)[si] = 1;
831
+            (*digests)[si] = folder->UnpackCRC;
832
+            si++;
833
+          }
834
+          else
835
+          {
836
+            UInt32 j;
837
+            for (j = 0; j < numSubstreams; j++, digestIndex++)
838
+            {
839
+              (*digestsDefined)[si] = digestsDefined2[digestIndex];
840
+              (*digests)[si] = digests2[digestIndex];
841
+              si++;
842
+            }
843
+          }
844
+        }
845
+      }
846
+      IAlloc_Free(allocTemp, digestsDefined2);
847
+      IAlloc_Free(allocTemp, digests2);
848
+      RINOK(res);
849
+    }
850
+    else if (type == k7zIdEnd)
851
+      return SZ_OK;
852
+    else
853
+    {
854
+      RINOK(SzSkeepData(sd));
855
+    }
856
+    RINOK(SzReadID(sd, &type));
857
+  }
858
+}
859
+
860
+
861
+static SRes SzReadStreamsInfo(
862
+    CSzData *sd,
863
+    UInt64 *dataOffset,
864
+    CSzAr *p,
865
+    UInt32 *numUnpackStreams,
866
+    UInt64 **unpackSizes, /* allocTemp */
867
+    Byte **digestsDefined,   /* allocTemp */
868
+    UInt32 **digests,        /* allocTemp */
869
+    ISzAlloc *alloc,
870
+    ISzAlloc *allocTemp)
871
+{
872
+  for (;;)
873
+  {
874
+    UInt64 type;
875
+    RINOK(SzReadID(sd, &type));
876
+    if ((UInt64)(int)type != type)
877
+      return SZ_ERROR_UNSUPPORTED;
878
+    switch((int)type)
879
+    {
880
+      case k7zIdEnd:
881
+        return SZ_OK;
882
+      case k7zIdPackInfo:
883
+      {
884
+        RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams,
885
+            &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc));
886
+        break;
887
+      }
888
+      case k7zIdUnpackInfo:
889
+      {
890
+        RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp));
891
+        break;
892
+      }
893
+      case k7zIdSubStreamsInfo:
894
+      {
895
+        RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders,
896
+            numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp));
897
+        break;
898
+      }
899
+      default:
900
+        return SZ_ERROR_UNSUPPORTED;
901
+    }
902
+  }
903
+}
904
+
905
+size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
906
+{
907
+  size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
908
+  if (dest != 0)
909
+  {
910
+    size_t i;
911
+    const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2);
912
+    for (i = 0; i < len; i++)
913
+      dest[i] = GetUi16(src + i * 2);
914
+  }
915
+  return len;
916
+}
917
+
918
+static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes)
919
+{
920
+  UInt32 i;
921
+  size_t pos = 0;
922
+  for (i = 0; i < numFiles; i++)
923
+  {
924
+    sizes[i] = pos;
925
+    for (;;)
926
+    {
927
+      if (pos >= size)
928
+        return SZ_ERROR_ARCHIVE;
929
+      if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0)
930
+        break;
931
+      pos++;
932
+    }
933
+    pos++;
934
+  }
935
+  sizes[i] = pos;
936
+  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
937
+}
938
+
939
+static SRes SzReadHeader2(
940
+    CSzArEx *p,   /* allocMain */
941
+    CSzData *sd,
942
+    UInt64 **unpackSizes,  /* allocTemp */
943
+    Byte **digestsDefined,    /* allocTemp */
944
+    UInt32 **digests,         /* allocTemp */
945
+    Byte **emptyStreamVector, /* allocTemp */
946
+    Byte **emptyFileVector,   /* allocTemp */
947
+    Byte **lwtVector,         /* allocTemp */
948
+    ISzAlloc *allocMain,
949
+    ISzAlloc *allocTemp)
950
+{
951
+  UInt64 type;
952
+  UInt32 numUnpackStreams = 0;
953
+  UInt32 numFiles = 0;
954
+  CSzFileItem *files = 0;
955
+  UInt32 numEmptyStreams = 0;
956
+  UInt32 i;
957
+
958
+  RINOK(SzReadID(sd, &type));
959
+
960
+  if (type == k7zIdArchiveProperties)
961
+  {
962
+    RINOK(SzReadArchiveProperties(sd));
963
+    RINOK(SzReadID(sd, &type));
964
+  }
965
+ 
966
+ 
967
+  if (type == k7zIdMainStreamsInfo)
968
+  {
969
+    RINOK(SzReadStreamsInfo(sd,
970
+        &p->dataPos,
971
+        &p->db,
972
+        &numUnpackStreams,
973
+        unpackSizes,
974
+        digestsDefined,
975
+        digests, allocMain, allocTemp));
976
+    p->dataPos += p->startPosAfterHeader;
977
+    RINOK(SzReadID(sd, &type));
978
+  }
979
+
980
+  if (type == k7zIdEnd)
981
+    return SZ_OK;
982
+  if (type != k7zIdFilesInfo)
983
+    return SZ_ERROR_ARCHIVE;
984
+  
985
+  RINOK(SzReadNumber32(sd, &numFiles));
986
+  p->db.NumFiles = numFiles;
987
+
988
+  MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);
989
+
990
+  p->db.Files = files;
991
+  for (i = 0; i < numFiles; i++)
992
+    SzFile_Init(files + i);
993
+
994
+  for (;;)
995
+  {
996
+    UInt64 type;
997
+    UInt64 size;
998
+    RINOK(SzReadID(sd, &type));
999
+    if (type == k7zIdEnd)
1000
+      break;
1001
+    RINOK(SzReadNumber(sd, &size));
1002
+    if (size > sd->Size)
1003
+      return SZ_ERROR_ARCHIVE;
1004
+    if ((UInt64)(int)type != type)
1005
+    {
1006
+      RINOK(SzSkeepDataSize(sd, size));
1007
+    }
1008
+    else
1009
+    switch((int)type)
1010
+    {
1011
+      case k7zIdName:
1012
+      {
1013
+        size_t namesSize;
1014
+        RINOK(SzReadSwitch(sd));
1015
+        namesSize = (size_t)size - 1;
1016
+        if ((namesSize & 1) != 0)
1017
+          return SZ_ERROR_ARCHIVE;
1018
+        if (!Buf_Create(&p->FileNames, namesSize, allocMain))
1019
+          return SZ_ERROR_MEM;
1020
+        MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
1021
+        memcpy(p->FileNames.data, sd->Data, namesSize);
1022
+        RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))
1023
+        RINOK(SzSkeepDataSize(sd, namesSize));
1024
+        break;
1025
+      }
1026
+      case k7zIdEmptyStream:
1027
+      {
1028
+        RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));
1029
+        numEmptyStreams = 0;
1030
+        for (i = 0; i < numFiles; i++)
1031
+          if ((*emptyStreamVector)[i])
1032
+            numEmptyStreams++;
1033
+        break;
1034
+      }
1035
+      case k7zIdEmptyFile:
1036
+      {
1037
+        RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));
1038
+        break;
1039
+      }
1040
+      case k7zIdWinAttributes:
1041
+      {
1042
+        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
1043
+        RINOK(SzReadSwitch(sd));
1044
+        for (i = 0; i < numFiles; i++)
1045
+        {
1046
+          CSzFileItem *f = &files[i];
1047
+          Byte defined = (*lwtVector)[i];
1048
+          f->AttribDefined = defined;
1049
+          f->Attrib = 0;
1050
+          if (defined)
1051
+          {
1052
+            RINOK(SzReadUInt32(sd, &f->Attrib));
1053
+          }
1054
+        }
1055
+        IAlloc_Free(allocTemp, *lwtVector);
1056
+        *lwtVector = NULL;
1057
+        break;
1058
+      }
1059
+      case k7zIdMTime:
1060
+      {
1061
+        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
1062
+        RINOK(SzReadSwitch(sd));
1063
+        for (i = 0; i < numFiles; i++)
1064
+        {
1065
+          CSzFileItem *f = &files[i];
1066
+          Byte defined = (*lwtVector)[i];
1067
+          f->MTimeDefined = defined;
1068
+          f->MTime.Low = f->MTime.High = 0;
1069
+          if (defined)
1070
+          {
1071
+            RINOK(SzReadUInt32(sd, &f->MTime.Low));
1072
+            RINOK(SzReadUInt32(sd, &f->MTime.High));
1073
+          }
1074
+        }
1075
+        IAlloc_Free(allocTemp, *lwtVector);
1076
+        *lwtVector = NULL;
1077
+        break;
1078
+      }
1079
+      default:
1080
+      {
1081
+        RINOK(SzSkeepDataSize(sd, size));
1082
+      }
1083
+    }
1084
+  }
1085
+
1086
+  {
1087
+    UInt32 emptyFileIndex = 0;
1088
+    UInt32 sizeIndex = 0;
1089
+    for (i = 0; i < numFiles; i++)
1090
+    {
1091
+      CSzFileItem *file = files + i;
1092
+      file->IsAnti = 0;
1093
+      if (*emptyStreamVector == 0)
1094
+        file->HasStream = 1;
1095
+      else
1096
+        file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
1097
+      if (file->HasStream)
1098
+      {
1099
+        file->IsDir = 0;
1100
+        file->Size = (*unpackSizes)[sizeIndex];
1101
+        file->Crc = (*digests)[sizeIndex];
1102
+        file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex];
1103
+        sizeIndex++;
1104
+      }
1105
+      else
1106
+      {
1107
+        if (*emptyFileVector == 0)
1108
+          file->IsDir = 1;
1109
+        else
1110
+          file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
1111
+        emptyFileIndex++;
1112
+        file->Size = 0;
1113
+        file->Crc = 0;
1114
+        file->CrcDefined = 0;
1115
+      }
1116
+    }
1117
+  }
1118
+  return SzArEx_Fill(p, allocMain);
1119
+}
1120
+
1121
+static SRes SzReadHeader(
1122
+    CSzArEx *p,
1123
+    CSzData *sd,
1124
+    ISzAlloc *allocMain,
1125
+    ISzAlloc *allocTemp)
1126
+{
1127
+  UInt64 *unpackSizes = 0;
1128
+  Byte *digestsDefined = 0;
1129
+  UInt32 *digests = 0;
1130
+  Byte *emptyStreamVector = 0;
1131
+  Byte *emptyFileVector = 0;
1132
+  Byte *lwtVector = 0;
1133
+  SRes res = SzReadHeader2(p, sd,
1134
+      &unpackSizes, &digestsDefined, &digests,
1135
+      &emptyStreamVector, &emptyFileVector, &lwtVector,
1136
+      allocMain, allocTemp);
1137
+  IAlloc_Free(allocTemp, unpackSizes);
1138
+  IAlloc_Free(allocTemp, digestsDefined);
1139
+  IAlloc_Free(allocTemp, digests);
1140
+  IAlloc_Free(allocTemp, emptyStreamVector);
1141
+  IAlloc_Free(allocTemp, emptyFileVector);
1142
+  IAlloc_Free(allocTemp, lwtVector);
1143
+  return res;
1144
+}
1145
+
1146
+static SRes SzReadAndDecodePackedStreams2(
1147
+    ILookInStream *inStream,
1148
+    CSzData *sd,
1149
+    CBuf *outBuffer,
1150
+    UInt64 baseOffset,
1151
+    CSzAr *p,
1152
+    UInt64 **unpackSizes,
1153
+    Byte **digestsDefined,
1154
+    UInt32 **digests,
1155
+    ISzAlloc *allocTemp)
1156
+{
1157
+
1158
+  UInt32 numUnpackStreams = 0;
1159
+  UInt64 dataStartPos;
1160
+  CSzFolder *folder;
1161
+  UInt64 unpackSize;
1162
+  SRes res;
1163
+
1164
+  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,
1165
+      &numUnpackStreams,  unpackSizes, digestsDefined, digests,
1166
+      allocTemp, allocTemp));
1167
+  
1168
+  dataStartPos += baseOffset;
1169
+  if (p->NumFolders != 1)
1170
+    return SZ_ERROR_ARCHIVE;
1171
+
1172
+  folder = p->Folders;
1173
+  unpackSize = SzFolder_GetUnpackSize(folder);
1174
+  
1175
+  RINOK(LookInStream_SeekTo(inStream, dataStartPos));
1176
+
1177
+  if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))
1178
+    return SZ_ERROR_MEM;
1179
+  
1180
+  res = SzFolder_Decode(folder, p->PackSizes,
1181
+          inStream, dataStartPos,
1182
+          outBuffer->data, (size_t)unpackSize, allocTemp);
1183
+  RINOK(res);
1184
+  if (folder->UnpackCRCDefined)
1185
+    if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)
1186
+      return SZ_ERROR_CRC;
1187
+  return SZ_OK;
1188
+}
1189
+
1190
+static SRes SzReadAndDecodePackedStreams(
1191
+    ILookInStream *inStream,
1192
+    CSzData *sd,
1193
+    CBuf *outBuffer,
1194
+    UInt64 baseOffset,
1195
+    ISzAlloc *allocTemp)
1196
+{
1197
+  CSzAr p;
1198
+  UInt64 *unpackSizes = 0;
1199
+  Byte *digestsDefined = 0;
1200
+  UInt32 *digests = 0;
1201
+  SRes res;
1202
+  SzAr_Init(&p);
1203
+  res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
1204
+    &p, &unpackSizes, &digestsDefined, &digests,
1205
+    allocTemp);
1206
+  SzAr_Free(&p, allocTemp);
1207
+  IAlloc_Free(allocTemp, unpackSizes);
1208
+  IAlloc_Free(allocTemp, digestsDefined);
1209
+  IAlloc_Free(allocTemp, digests);
1210
+  return res;
1211
+}
1212
+
1213
+static SRes SzArEx_Open2(
1214
+    CSzArEx *p,
1215
+    ILookInStream *inStream,
1216
+    ISzAlloc *allocMain,
1217
+    ISzAlloc *allocTemp)
1218
+{
1219
+  Byte header[k7zStartHeaderSize];
1220
+  Int64 startArcPos;
1221
+  UInt64 nextHeaderOffset, nextHeaderSize;
1222
+  size_t nextHeaderSizeT;
1223
+  UInt32 nextHeaderCRC;
1224
+  CBuf buffer;
1225
+  SRes res;
1226
+
1227
+  startArcPos = 0;
1228
+  RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));
1229
+
1230
+  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
1231
+
1232
+  if (!TestSignatureCandidate(header))
1233
+    return SZ_ERROR_NO_ARCHIVE;
1234
+  if (header[6] != k7zMajorVersion)
1235
+    return SZ_ERROR_UNSUPPORTED;
1236
+
1237
+  nextHeaderOffset = GetUi64(header + 12);
1238
+  nextHeaderSize = GetUi64(header + 20);
1239
+  nextHeaderCRC = GetUi32(header + 28);
1240
+
1241
+  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
1242
+  
1243
+  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
1244
+    return SZ_ERROR_CRC;
1245
+
1246
+  nextHeaderSizeT = (size_t)nextHeaderSize;
1247
+  if (nextHeaderSizeT != nextHeaderSize)
1248
+    return SZ_ERROR_MEM;
1249
+  if (nextHeaderSizeT == 0)
1250
+    return SZ_OK;
1251
+  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
1252
+      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
1253
+    return SZ_ERROR_NO_ARCHIVE;
1254
+
1255
+  {
1256
+    Int64 pos = 0;
1257
+    RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
1258
+    if ((UInt64)pos < startArcPos + nextHeaderOffset ||
1259
+        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
1260
+        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
1261
+      return SZ_ERROR_INPUT_EOF;
1262
+  }
1263
+
1264
+  RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
1265
+
1266
+  if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))
1267
+    return SZ_ERROR_MEM;
1268
+
1269
+  res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT);
1270
+  if (res == SZ_OK)
1271
+  {
1272
+    res = SZ_ERROR_ARCHIVE;
1273
+    if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)
1274
+    {
1275
+      CSzData sd;
1276
+      UInt64 type;
1277
+      sd.Data = buffer.data;
1278
+      sd.Size = buffer.size;
1279
+      res = SzReadID(&sd, &type);
1280
+      if (res == SZ_OK)
1281
+      {
1282
+        if (type == k7zIdEncodedHeader)
1283
+        {
1284
+          CBuf outBuffer;
1285
+          Buf_Init(&outBuffer);
1286
+          res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp);
1287
+          if (res != SZ_OK)
1288
+            Buf_Free(&outBuffer, allocTemp);
1289
+          else
1290
+          {
1291
+            Buf_Free(&buffer, allocTemp);
1292
+            buffer.data = outBuffer.data;
1293
+            buffer.size = outBuffer.size;
1294
+            sd.Data = buffer.data;
1295
+            sd.Size = buffer.size;
1296
+            res = SzReadID(&sd, &type);
1297
+          }
1298
+        }
1299
+      }
1300
+      if (res == SZ_OK)
1301
+      {
1302
+        if (type == k7zIdHeader)
1303
+          res = SzReadHeader(p, &sd, allocMain, allocTemp);
1304
+        else
1305
+          res = SZ_ERROR_UNSUPPORTED;
1306
+      }
1307
+    }
1308
+  }
1309
+  Buf_Free(&buffer, allocTemp);
1310
+  return res;
1311
+}
1312
+
1313
+SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp)
1314
+{
1315
+  SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
1316
+  if (res != SZ_OK)
1317
+    SzArEx_Free(p, allocMain);
1318
+  return res;
1319
+}
1320
+
1321
+SRes SzArEx_Extract(
1322
+    const CSzArEx *p,
1323
+    ILookInStream *inStream,
1324
+    UInt32 fileIndex,
1325
+    UInt32 *blockIndex,
1326
+    Byte **outBuffer,
1327
+    size_t *outBufferSize,
1328
+    size_t *offset,
1329
+    size_t *outSizeProcessed,
1330
+    ISzAlloc *allocMain,
1331
+    ISzAlloc *allocTemp)
1332
+{
1333
+  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
1334
+  SRes res = SZ_OK;
1335
+  *offset = 0;
1336
+  *outSizeProcessed = 0;
1337
+  if (folderIndex == (UInt32)-1)
1338
+  {
1339
+    IAlloc_Free(allocMain, *outBuffer);
1340
+    *blockIndex = folderIndex;
1341
+    *outBuffer = 0;
1342
+    *outBufferSize = 0;
1343
+    return SZ_OK;
1344
+  }
1345
+
1346
+  if (*outBuffer == 0 || *blockIndex != folderIndex)
1347
+  {
1348
+    CSzFolder *folder = p->db.Folders + folderIndex;
1349
+    UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
1350
+    size_t unpackSize = (size_t)unpackSizeSpec;
1351
+    UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
1352
+
1353
+    if (unpackSize != unpackSizeSpec)
1354
+      return SZ_ERROR_MEM;
1355
+    *blockIndex = folderIndex;
1356
+    IAlloc_Free(allocMain, *outBuffer);
1357
+    *outBuffer = 0;
1358
+    
1359
+    RINOK(LookInStream_SeekTo(inStream, startOffset));
1360
+    
1361
+    if (res == SZ_OK)
1362
+    {
1363
+      *outBufferSize = unpackSize;
1364
+      if (unpackSize != 0)
1365
+      {
1366
+        *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
1367
+        if (*outBuffer == 0)
1368
+          res = SZ_ERROR_MEM;
1369
+      }
1370
+      if (res == SZ_OK)
1371
+      {
1372
+        res = SzFolder_Decode(folder,
1373
+          p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],
1374
+          inStream, startOffset,
1375
+          *outBuffer, unpackSize, allocTemp);
1376
+        if (res == SZ_OK)
1377
+        {
1378
+          if (folder->UnpackCRCDefined)
1379
+          {
1380
+            if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
1381
+              res = SZ_ERROR_CRC;
1382
+          }
1383
+        }
1384
+      }
1385
+    }
1386
+  }
1387
+  if (res == SZ_OK)
1388
+  {
1389
+    UInt32 i;
1390
+    CSzFileItem *fileItem = p->db.Files + fileIndex;
1391
+    *offset = 0;
1392
+    for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
1393
+      *offset += (UInt32)p->db.Files[i].Size;
1394
+    *outSizeProcessed = (size_t)fileItem->Size;
1395
+    if (*offset + *outSizeProcessed > *outBufferSize)
1396
+      return SZ_ERROR_FAIL;
1397
+    if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)
1398
+      res = SZ_ERROR_CRC;
1399
+  }
1400
+  return res;
1401
+}
... ...
@@ -1,5 +1,5 @@
1 1
 /* 7zStream.c -- 7z Stream functions
2
-2008-11-23 : Igor Pavlov : Public domain */
2
+2010-03-11 : Igor Pavlov : Public domain */
3 3
 
4 4
 #include <string.h>
5 5
 
... ...
@@ -39,7 +39,7 @@ SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
39 39
 
40 40
 SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
41 41
 {
42
-  void *lookBuf;
42
+  const void *lookBuf;
43 43
   if (*size == 0)
44 44
     return SZ_OK;
45 45
   RINOK(stream->Look(stream, &lookBuf, size));
... ...
@@ -66,7 +66,7 @@ SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
66 66
   return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
67 67
 }
68 68
 
69
-static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size)
69
+static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
70 70
 {
71 71
   SRes res = SZ_OK;
72 72
   CLookToRead *p = (CLookToRead *)pp;
... ...
@@ -84,7 +84,7 @@ static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size)
84 84
   return res;
85 85
 }
86 86
 
87
-static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size)
87
+static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
88 88
 {
89 89
   SRes res = SZ_OK;
90 90
   CLookToRead *p = (CLookToRead *)pp;
91 91
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+#define MY_VER_MAJOR 9
1
+#define MY_VER_MINOR 20
2
+#define MY_VER_BUILD 0
3
+#define MY_VERSION "9.20"
4
+#define MY_DATE "2010-11-18"
5
+#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
6
+#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
0 7
deleted file mode 100644
... ...
@@ -1,257 +0,0 @@
1
-/* 7zDecode.c -- Decoding from 7z folder
2
-2008-11-23 : Igor Pavlov : Public domain */
3
-
4
-#include <string.h>
5
-
6
-#include "../../Bcj2.h"
7
-#include "../../Bra.h"
8
-#include "../../LzmaDec.h"
9
-#include "7zDecode.h"
10
-
11
-#define k_Copy 0
12
-#define k_LZMA 0x30101
13
-#define k_BCJ 0x03030103
14
-#define k_BCJ2 0x0303011B
15
-
16
-static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
17
-    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
18
-{
19
-  CLzmaDec state;
20
-  SRes res = SZ_OK;
21
-
22
-  LzmaDec_Construct(&state);
23
-  RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
24
-  state.dic = outBuffer;
25
-  state.dicBufSize = outSize;
26
-  LzmaDec_Init(&state);
27
-
28
-  for (;;)
29
-  {
30
-    Byte *inBuf = NULL;
31
-    size_t lookahead = (1 << 18);
32
-    if (lookahead > inSize)
33
-      lookahead = (size_t)inSize;
34
-    res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead);
35
-    if (res != SZ_OK)
36
-      break;
37
-
38
-    {
39
-      SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
40
-      ELzmaStatus status;
41
-      res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
42
-      lookahead -= inProcessed;
43
-      inSize -= inProcessed;
44
-      if (res != SZ_OK)
45
-        break;
46
-      if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
47
-      {
48
-        if (state.dicBufSize != outSize || lookahead != 0 ||
49
-            (status != LZMA_STATUS_FINISHED_WITH_MARK &&
50
-             status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
51
-          res = SZ_ERROR_DATA;
52
-        break;
53
-      }
54
-      res = inStream->Skip((void *)inStream, inProcessed);
55
-      if (res != SZ_OK)
56
-        break;
57
-    }
58
-  }
59
-
60
-  LzmaDec_FreeProbs(&state, allocMain);
61
-  return res;
62
-}
63
-
64
-static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
65
-{
66
-  while (inSize > 0)
67
-  {
68
-    void *inBuf;
69
-    size_t curSize = (1 << 18);
70
-    if (curSize > inSize)
71
-      curSize = (size_t)inSize;
72
-    RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize));
73
-    if (curSize == 0)
74
-      return SZ_ERROR_INPUT_EOF;
75
-    memcpy(outBuffer, inBuf, curSize);
76
-    outBuffer += curSize;
77
-    inSize -= curSize;
78
-    RINOK(inStream->Skip((void *)inStream, curSize));
79
-  }
80
-  return SZ_OK;
81
-}
82
-
83
-#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
84
-#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
85
-#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
86
-#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
87
-
88
-SRes CheckSupportedFolder(const CSzFolder *f)
89
-{
90
-  if (f->NumCoders < 1 || f->NumCoders > 4)
91
-    return SZ_ERROR_UNSUPPORTED;
92
-  if (IS_UNSUPPORTED_CODER(f->Coders[0]))
93
-    return SZ_ERROR_UNSUPPORTED;
94
-  if (f->NumCoders == 1)
95
-  {
96
-    if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
97
-      return SZ_ERROR_UNSUPPORTED;
98
-    return SZ_OK;
99
-  }
100
-  if (f->NumCoders == 2)
101
-  {
102
-    if (IS_NO_BCJ(f->Coders[1]) ||
103
-        f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
104
-        f->NumBindPairs != 1 ||
105
-        f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
106
-      return SZ_ERROR_UNSUPPORTED;
107
-    return SZ_OK;
108
-  }
109
-  if (f->NumCoders == 4)
110
-  {
111
-    if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
112
-        IS_UNSUPPORTED_CODER(f->Coders[2]) ||
113
-        IS_NO_BCJ2(f->Coders[3]))
114
-      return SZ_ERROR_UNSUPPORTED;
115
-    if (f->NumPackStreams != 4 ||
116
-        f->PackStreams[0] != 2 ||
117
-        f->PackStreams[1] != 6 ||
118
-        f->PackStreams[2] != 1 ||
119
-        f->PackStreams[3] != 0 ||
120
-        f->NumBindPairs != 3 ||
121
-        f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
122
-        f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
123
-        f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
124
-      return SZ_ERROR_UNSUPPORTED;
125
-    return SZ_OK;
126
-  }
127
-  return SZ_ERROR_UNSUPPORTED;
128
-}
129
-
130
-UInt64 GetSum(const UInt64 *values, UInt32 index)
131
-{
132
-  UInt64 sum = 0;
133
-  UInt32 i;
134
-  for (i = 0; i < index; i++)
135
-    sum += values[i];
136
-  return sum;
137
-}
138
-
139
-SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
140
-    ILookInStream *inStream, UInt64 startPos,
141
-    Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
142
-    Byte *tempBuf[])
143
-{
144
-  UInt32 ci;
145
-  SizeT tempSizes[3] = { 0, 0, 0};
146
-  SizeT tempSize3 = 0;
147
-  Byte *tempBuf3 = 0;
148
-
149
-  RINOK(CheckSupportedFolder(folder));
150
-
151
-  for (ci = 0; ci < folder->NumCoders; ci++)
152
-  {
153
-    CSzCoderInfo *coder = &folder->Coders[ci];
154
-
155
-    if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
156
-    {
157
-      UInt32 si = 0;
158
-      UInt64 offset;
159
-      UInt64 inSize;
160
-      Byte *outBufCur = outBuffer;
161
-      SizeT outSizeCur = outSize;
162
-      if (folder->NumCoders == 4)
163
-      {
164
-        UInt32 indices[] = { 3, 2, 0 };
165
-        UInt64 unpackSize = folder->UnpackSizes[ci];
166
-        si = indices[ci];
167
-        if (ci < 2)
168
-        {
169
-          Byte *temp;
170
-          outSizeCur = (SizeT)unpackSize;
171
-          if (outSizeCur != unpackSize)
172
-            return SZ_ERROR_MEM;
173
-	  if (outSizeCur)
174
-	      temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
175
-	  else
176
-	      temp = 0;
177
-          if (temp == 0 && outSizeCur != 0)
178
-            return SZ_ERROR_MEM;
179
-          outBufCur = tempBuf[1 - ci] = temp;
180
-          tempSizes[1 - ci] = outSizeCur;
181
-        }
182
-        else if (ci == 2)
183
-        {
184
-          if (unpackSize > outSize) /* check it */
185
-            return SZ_ERROR_PARAM;
186
-          tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
187
-          tempSize3 = outSizeCur = (SizeT)unpackSize;
188
-        }
189
-        else
190
-          return SZ_ERROR_UNSUPPORTED;
191
-      }
192
-      offset = GetSum(packSizes, si);
193
-      inSize = packSizes[si];
194
-      RINOK(LookInStream_SeekTo(inStream, startPos + offset));
195
-
196
-      if (coder->MethodID == k_Copy)
197
-      {
198
-        if (inSize != outSizeCur) /* check it */
199
-          return SZ_ERROR_DATA;
200
-        RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
201
-      }
202
-      else
203
-      {
204
-        RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
205
-      }
206
-    }
207
-    else if (coder->MethodID == k_BCJ)
208
-    {
209
-      UInt32 state;
210
-      if (ci != 1)
211
-        return SZ_ERROR_UNSUPPORTED;
212
-      x86_Convert_Init(state);
213
-      x86_Convert(outBuffer, outSize, 0, &state, 0);
214
-    }
215
-    else if (coder->MethodID == k_BCJ2)
216
-    {
217
-      UInt64 offset = GetSum(packSizes, 1);
218
-      UInt64 s3Size = packSizes[1];
219
-      SRes res;
220
-      if (ci != 3)
221
-        return SZ_ERROR_UNSUPPORTED;
222
-      RINOK(LookInStream_SeekTo(inStream, startPos + offset));
223
-      tempSizes[2] = (SizeT)s3Size;
224
-      if (tempSizes[2] != s3Size)
225
-        return SZ_ERROR_MEM;
226
-      tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
227
-      if (tempBuf[2] == 0 && tempSizes[2] != 0)
228
-        return SZ_ERROR_MEM;
229
-      res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
230
-      RINOK(res)
231
-
232
-      res = Bcj2_Decode(
233
-          tempBuf3, tempSize3,
234
-          tempBuf[0], tempSizes[0],
235
-          tempBuf[1], tempSizes[1],
236
-          tempBuf[2], tempSizes[2],
237
-          outBuffer, outSize);
238
-      RINOK(res)
239
-    }
240
-    else
241
-      return SZ_ERROR_UNSUPPORTED;
242
-  }
243
-  return SZ_OK;
244
-}
245
-
246
-SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
247
-    ILookInStream *inStream, UInt64 startPos,
248
-    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
249
-{
250
-  Byte *tempBuf[3] = { 0, 0, 0};
251
-  int i;
252
-  SRes res = SzDecode2(packSizes, folder, inStream, startPos,
253
-      outBuffer, (SizeT)outSize, allocMain, tempBuf);
254
-  for (i = 0; i < 3; i++)
255
-    IAlloc_Free(allocMain, tempBuf[i]);
256
-  return res;
257
-}
258 1
deleted file mode 100644
... ...
@@ -1,13 +0,0 @@
1
-/* 7zDecode.h -- Decoding from 7z folder
2
-2008-11-23 : Igor Pavlov : Public domain */
3
-
4
-#ifndef __7Z_DECODE_H
5
-#define __7Z_DECODE_H
6
-
7
-#include "7zItem.h"
8
-
9
-SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
10
-    ILookInStream *stream, UInt64 startPos,
11
-    Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
12
-
13
-#endif
14 1
deleted file mode 100644
... ...
@@ -1,93 +0,0 @@
1
-/* 7zExtract.c -- Extracting from 7z archive
2
-2008-11-23 : Igor Pavlov : Public domain */
3
-
4
-#include "../../7zCrc.h"
5
-#include "7zDecode.h"
6
-#include "7zExtract.h"
7
-
8
-SRes SzAr_Extract(
9
-    const CSzArEx *p,
10
-    ILookInStream *inStream,
11
-    UInt32 fileIndex,
12
-    UInt32 *blockIndex,
13
-    Byte **outBuffer,
14
-    size_t *outBufferSize,
15
-    size_t *offset,
16
-    size_t *outSizeProcessed,
17
-    ISzAlloc *allocMain,
18
-    ISzAlloc *allocTemp)
19
-{
20
-  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
21
-  SRes res = SZ_OK;
22
-  *offset = 0;
23
-  *outSizeProcessed = 0;
24
-  if (folderIndex == (UInt32)-1)
25
-  {
26
-    IAlloc_Free(allocMain, *outBuffer);
27
-    *blockIndex = folderIndex;
28
-    *outBuffer = 0;
29
-    *outBufferSize = 0;
30
-    return SZ_OK;
31
-  }
32
-
33
-  if (*outBuffer == 0 || *blockIndex != folderIndex)
34
-  {
35
-    CSzFolder *folder = p->db.Folders + folderIndex;
36
-    UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
37
-    size_t unpackSize = (size_t)unpackSizeSpec;
38
-    UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
39
-
40
-    if (unpackSize != unpackSizeSpec)
41
-      return SZ_ERROR_MEM;
42
-    *blockIndex = folderIndex;
43
-    IAlloc_Free(allocMain, *outBuffer);
44
-    *outBuffer = 0;
45
-    
46
-    RINOK(LookInStream_SeekTo(inStream, startOffset));
47
-    
48
-    if (res == SZ_OK)
49
-    {
50
-      *outBufferSize = unpackSize;
51
-      if (unpackSize != 0)
52
-      {
53
-        *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
54
-        if (*outBuffer == 0)
55
-          res = SZ_ERROR_MEM;
56
-      }
57
-      if (res == SZ_OK)
58
-      {
59
-        res = SzDecode(p->db.PackSizes +
60
-          p->FolderStartPackStreamIndex[folderIndex], folder,
61
-          inStream, startOffset,
62
-          *outBuffer, unpackSize, allocTemp);
63
-        if (res == SZ_OK)
64
-        {
65
-          if (folder->UnpackCRCDefined)
66
-          {
67
-            if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
68
-              res = SZ_ERROR_CRC;
69
-          }
70
-        }
71
-      }
72
-    }
73
-  }
74
-  if (res == SZ_OK)
75
-  {
76
-    UInt32 i;
77
-    CSzFileItem *fileItem = p->db.Files + fileIndex;
78
-    *offset = 0;
79
-    for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
80
-      *offset += (UInt32)p->db.Files[i].Size;
81
-    *outSizeProcessed = (size_t)fileItem->Size;
82
-    if (*offset + *outSizeProcessed > *outBufferSize)
83
-      return SZ_ERROR_FAIL;
84
-    {
85
-      if (fileItem->FileCRCDefined)
86
-      {
87
-        if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
88
-          res = SZ_ERROR_CRC;
89
-      }
90
-    }
91
-  }
92
-  return res;
93
-}
94 1
deleted file mode 100644
... ...
@@ -1,41 +0,0 @@
1
-/* 7zExtract.h -- Extracting from 7z archive
2
-2008-11-23 : Igor Pavlov : Public domain */
3
-
4
-#ifndef __7Z_EXTRACT_H
5
-#define __7Z_EXTRACT_H
6
-
7
-#include "7zIn.h"
8
-
9
-/*
10
-  SzExtract extracts file from archive
11
-
12
-  *outBuffer must be 0 before first call for each new archive.
13
-
14
-  Extracting cache:
15
-    If you need to decompress more than one file, you can send
16
-    these values from previous call:
17
-      *blockIndex,
18
-      *outBuffer,
19
-      *outBufferSize
20
-    You can consider "*outBuffer" as cache of solid block. If your archive is solid,
21
-    it will increase decompression speed.
22
-  
23
-    If you use external function, you can declare these 3 cache variables
24
-    (blockIndex, outBuffer, outBufferSize) as static in that external function.
25
-    
26
-    Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
27
-*/
28
-
29
-SRes SzAr_Extract(
30
-    const CSzArEx *db,
31
-    ILookInStream *inStream,
32
-    UInt32 fileIndex,         /* index of file */
33
-    UInt32 *blockIndex,       /* index of solid block */
34
-    Byte **outBuffer,         /* pointer to pointer to output buffer (allocated with allocMain) */
35
-    size_t *outBufferSize,    /* buffer size for output buffer */
36
-    size_t *offset,           /* offset of stream for required file in *outBuffer */
37
-    size_t *outSizeProcessed, /* size of file in *outBuffer */
38
-    ISzAlloc *allocMain,
39
-    ISzAlloc *allocTemp);
40
-
41
-#endif
42 1
deleted file mode 100644
... ...
@@ -1,6 +0,0 @@
1
-/*  7zHeader.c -- 7z Headers
2
-2008-10-04 : Igor Pavlov : Public domain */
3
-
4
-#include "7zHeader.h"
5
-
6
-Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
7 1
deleted file mode 100644
... ...
@@ -1,57 +0,0 @@
1
-/* 7zHeader.h -- 7z Headers
2
-2008-10-04 : Igor Pavlov : Public domain */
3
-
4
-#ifndef __7Z_HEADER_H
5
-#define __7Z_HEADER_H
6
-
7
-#include "../../Types.h"
8
-
9
-#define k7zSignatureSize 6
10
-extern Byte k7zSignature[k7zSignatureSize];
11
-
12
-#define k7zMajorVersion 0
13
-
14
-#define k7zStartHeaderSize 0x20
15
-
16
-enum EIdEnum
17
-{
18
-  k7zIdEnd,
19
-    
20
-  k7zIdHeader,
21
-    
22
-  k7zIdArchiveProperties,
23
-    
24
-  k7zIdAdditionalStreamsInfo,
25
-  k7zIdMainStreamsInfo,
26
-  k7zIdFilesInfo,
27
-  
28
-  k7zIdPackInfo,
29
-  k7zIdUnpackInfo,
30
-  k7zIdSubStreamsInfo,
31
-  
32
-  k7zIdSize,
33
-  k7zIdCRC,
34
-  
35
-  k7zIdFolder,
36
-  
37
-  k7zIdCodersUnpackSize,
38
-  k7zIdNumUnpackStream,
39
-  
40
-  k7zIdEmptyStream,
41
-  k7zIdEmptyFile,
42
-  k7zIdAnti,
43
-  
44
-  k7zIdName,
45
-  k7zIdCTime,
46
-  k7zIdATime,
47
-  k7zIdMTime,
48
-  k7zIdWinAttributes,
49
-  k7zIdComment,
50
-  
51
-  k7zIdEncodedHeader,
52
-  
53
-  k7zIdStartPos,
54
-  k7zIdDummy
55
-};
56
-
57
-#endif
58 1
deleted file mode 100644
... ...
@@ -1,1229 +0,0 @@
1
-/* 7zIn.c -- 7z Input functions
2
-2008-12-31 : Igor Pavlov : Public domain */
3
-
4
-#include "../../7zCrc.h"
5
-#include "../../CpuArch.h"
6
-
7
-#include "7zDecode.h"
8
-#include "7zIn.h"
9
-
10
-#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; }
11
-
12
-#define NUM_FOLDER_CODERS_MAX 32
13
-#define NUM_CODER_STREAMS_MAX 32
14
-
15
-void SzArEx_Init(CSzArEx *p)
16
-{
17
-  SzAr_Init(&p->db);
18
-  p->FolderStartPackStreamIndex = 0;
19
-  p->PackStreamStartPositions = 0;
20
-  p->FolderStartFileIndex = 0;
21
-  p->FileIndexToFolderIndexMap = 0;
22
-}
23
-
24
-void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
25
-{
26
-  IAlloc_Free(alloc, p->FolderStartPackStreamIndex);
27
-  IAlloc_Free(alloc, p->PackStreamStartPositions);
28
-  IAlloc_Free(alloc, p->FolderStartFileIndex);
29
-  IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);
30
-  SzAr_Free(&p->db, alloc);
31
-  SzArEx_Init(p);
32
-}
33
-
34
-/*
35
-UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
36
-{
37
-  return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
38
-}
39
-
40
-UInt64 GetFilePackSize(int fileIndex) const
41
-{
42
-  int folderIndex = FileIndexToFolderIndexMap[fileIndex];
43
-  if (folderIndex >= 0)
44
-  {
45
-    const CSzFolder &folderInfo = Folders[folderIndex];
46
-    if (FolderStartFileIndex[folderIndex] == fileIndex)
47
-    return GetFolderFullPackSize(folderIndex);
48
-  }
49
-  return 0;
50
-}
51
-*/
52
-
53
-#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \
54
-  if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; }
55
-
56
-static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc)
57
-{
58
-  UInt32 startPos = 0;
59
-  UInt64 startPosSize = 0;
60
-  UInt32 i;
61
-  UInt32 folderIndex = 0;
62
-  UInt32 indexInFolder = 0;
63
-  MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc);
64
-  for (i = 0; i < p->db.NumFolders; i++)
65
-  {
66
-    p->FolderStartPackStreamIndex[i] = startPos;
67
-    startPos += p->db.Folders[i].NumPackStreams;
68
-  }
69
-
70
-  MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc);
71
-
72
-  for (i = 0; i < p->db.NumPackStreams; i++)
73
-  {
74
-    p->PackStreamStartPositions[i] = startPosSize;
75
-    startPosSize += p->db.PackSizes[i];
76
-  }
77
-
78
-  MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc);
79
-  MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc);
80
-
81
-  for (i = 0; i < p->db.NumFiles; i++)
82
-  {
83
-    CSzFileItem *file = p->db.Files + i;
84
-    int emptyStream = !file->HasStream;
85
-    if (emptyStream && indexInFolder == 0)
86
-    {
87
-      p->FileIndexToFolderIndexMap[i] = (UInt32)-1;
88
-      continue;
89
-    }
90
-    if (indexInFolder == 0)
91
-    {
92
-      /*
93
-      v3.13 incorrectly worked with empty folders
94
-      v4.07: Loop for skipping empty folders
95
-      */
96
-      for (;;)
97
-      {
98
-        if (folderIndex >= p->db.NumFolders)
99
-          return SZ_ERROR_ARCHIVE;
100
-        p->FolderStartFileIndex[folderIndex] = i;
101
-        if (p->db.Folders[folderIndex].NumUnpackStreams != 0)
102
-          break;
103
-        folderIndex++;
104
-      }
105
-    }
106
-    p->FileIndexToFolderIndexMap[i] = folderIndex;
107
-    if (emptyStream)
108
-      continue;
109
-    indexInFolder++;
110
-    if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams)
111
-    {
112
-      folderIndex++;
113
-      indexInFolder = 0;
114
-    }
115
-  }
116
-  return SZ_OK;
117
-}
118
-
119
-
120
-UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder)
121
-{
122
-  return p->dataPos +
123
-    p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
124
-}
125
-
126
-int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize)
127
-{
128
-  UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex];
129
-  CSzFolder *folder = p->db.Folders + folderIndex;
130
-  UInt64 size = 0;
131
-  UInt32 i;
132
-  for (i = 0; i < folder->NumPackStreams; i++)
133
-  {
134
-    UInt64 t = size + p->db.PackSizes[packStreamIndex + i];
135
-    if (t < size) /* check it */
136
-      return SZ_ERROR_FAIL;
137
-    size = t;
138
-  }
139
-  *resSize = size;
140
-  return SZ_OK;
141
-}
142
-
143
-
144
-/*
145
-SRes SzReadTime(const CObjectVector<CBuf> &dataVector,
146
-    CObjectVector<CSzFileItem> &files, UInt64 type)
147
-{
148
-  CBoolVector boolVector;
149
-  RINOK(ReadBoolVector2(files.Size(), boolVector))
150
-
151
-  CStreamSwitch streamSwitch;
152
-  RINOK(streamSwitch.Set(this, &dataVector));
153
-
154
-  for (int i = 0; i < files.Size(); i++)
155
-  {
156
-    CSzFileItem &file = files[i];
157
-    CArchiveFileTime fileTime;
158
-    bool defined = boolVector[i];
159
-    if (defined)
160
-    {
161
-      UInt32 low, high;
162
-      RINOK(SzReadUInt32(low));
163
-      RINOK(SzReadUInt32(high));
164
-      fileTime.dwLowDateTime = low;
165
-      fileTime.dwHighDateTime = high;
166
-    }
167
-    switch(type)
168
-    {
169
-      case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break;
170
-      case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break;
171
-      case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break;
172
-    }
173
-  }
174
-  return SZ_OK;
175
-}
176
-*/
177
-
178
-static int TestSignatureCandidate(Byte *testBytes)
179
-{
180
-  size_t i;
181
-  for (i = 0; i < k7zSignatureSize; i++)
182
-    if (testBytes[i] != k7zSignature[i])
183
-      return 0;
184
-  return 1;
185
-}
186
-
187
-typedef struct _CSzState
188
-{
189
-  Byte *Data;
190
-  size_t Size;
191
-}CSzData;
192
-
193
-static SRes SzReadByte(CSzData *sd, Byte *b)
194
-{
195
-  if (sd->Size == 0)
196
-    return SZ_ERROR_ARCHIVE;
197
-  sd->Size--;
198
-  *b = *sd->Data++;
199
-  return SZ_OK;
200
-}
201
-
202
-static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size)
203
-{
204
-  size_t i;
205
-  for (i = 0; i < size; i++)
206
-  {
207
-    RINOK(SzReadByte(sd, data + i));
208
-  }
209
-  return SZ_OK;
210
-}
211
-
212
-static SRes SzReadUInt32(CSzData *sd, UInt32 *value)
213
-{
214
-  int i;
215
-  *value = 0;
216
-  for (i = 0; i < 4; i++)
217
-  {
218
-    Byte b;
219
-    RINOK(SzReadByte(sd, &b));
220
-    *value |= ((UInt32)(b) << (8 * i));
221
-  }
222
-  return SZ_OK;
223
-}
224
-
225
-static SRes SzReadNumber(CSzData *sd, UInt64 *value)
226
-{
227
-  Byte firstByte;
228
-  Byte mask = 0x80;
229
-  int i;
230
-  RINOK(SzReadByte(sd, &firstByte));
231
-  *value = 0;
232
-  for (i = 0; i < 8; i++)
233
-  {
234
-    Byte b;
235
-    if ((firstByte & mask) == 0)
236
-    {
237
-      UInt64 highPart = firstByte & (mask - 1);
238
-      *value += (highPart << (8 * i));
239
-      return SZ_OK;
240
-    }
241
-    RINOK(SzReadByte(sd, &b));
242
-    *value |= ((UInt64)b << (8 * i));
243
-    mask >>= 1;
244
-  }
245
-  return SZ_OK;
246
-}
247
-
248
-static SRes SzReadNumber32(CSzData *sd, UInt32 *value)
249
-{
250
-  UInt64 value64;
251
-  RINOK(SzReadNumber(sd, &value64));
252
-  if (value64 >= 0x80000000)
253
-    return SZ_ERROR_UNSUPPORTED;
254
-  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
255
-    return SZ_ERROR_UNSUPPORTED;
256
-  *value = (UInt32)value64;
257
-  return SZ_OK;
258
-}
259
-
260
-static SRes SzReadID(CSzData *sd, UInt64 *value)
261
-{
262
-  return SzReadNumber(sd, value);
263
-}
264
-
265
-static SRes SzSkeepDataSize(CSzData *sd, UInt64 size)
266
-{
267
-  if (size > sd->Size)
268
-    return SZ_ERROR_ARCHIVE;
269
-  sd->Size -= (size_t)size;
270
-  sd->Data += (size_t)size;
271
-  return SZ_OK;
272
-}
273
-
274
-static SRes SzSkeepData(CSzData *sd)
275
-{
276
-  UInt64 size;
277
-  RINOK(SzReadNumber(sd, &size));
278
-  return SzSkeepDataSize(sd, size);
279
-}
280
-
281
-static SRes SzReadArchiveProperties(CSzData *sd)
282
-{
283
-  for (;;)
284
-  {
285
-    UInt64 type;
286
-    RINOK(SzReadID(sd, &type));
287
-    if (type == k7zIdEnd)
288
-      break;
289
-    SzSkeepData(sd);
290
-  }
291
-  return SZ_OK;
292
-}
293
-
294
-static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute)
295
-{
296
-  for (;;)
297
-  {
298
-    UInt64 type;
299
-    RINOK(SzReadID(sd, &type));
300
-    if (type == attribute)
301
-      return SZ_OK;
302
-    if (type == k7zIdEnd)
303
-      return SZ_ERROR_ARCHIVE;
304
-    RINOK(SzSkeepData(sd));
305
-  }
306
-}
307
-
308
-static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)
309
-{
310
-  Byte b = 0;
311
-  Byte mask = 0;
312
-  size_t i;
313
-  MY_ALLOC(Byte, *v, numItems, alloc);
314
-  for (i = 0; i < numItems; i++)
315
-  {
316
-    if (mask == 0)
317
-    {
318
-      RINOK(SzReadByte(sd, &b));
319
-      mask = 0x80;
320
-    }
321
-    (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);
322
-    mask >>= 1;
323
-  }
324
-  return SZ_OK;
325
-}
326
-
327
-static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc)
328
-{
329
-  Byte allAreDefined;
330
-  size_t i;
331
-  RINOK(SzReadByte(sd, &allAreDefined));
332
-  if (allAreDefined == 0)
333
-    return SzReadBoolVector(sd, numItems, v, alloc);
334
-  MY_ALLOC(Byte, *v, numItems, alloc);
335
-  for (i = 0; i < numItems; i++)
336
-    (*v)[i] = 1;
337
-  return SZ_OK;
338
-}
339
-
340
-static SRes SzReadHashDigests(
341
-    CSzData *sd,
342
-    size_t numItems,
343
-    Byte **digestsDefined,
344
-    UInt32 **digests,
345
-    ISzAlloc *alloc)
346
-{
347
-  size_t i;
348
-  RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc));
349
-  MY_ALLOC(UInt32, *digests, numItems, alloc);
350
-  for (i = 0; i < numItems; i++)
351
-    if ((*digestsDefined)[i])
352
-    {
353
-      RINOK(SzReadUInt32(sd, (*digests) + i));
354
-    }
355
-  return SZ_OK;
356
-}
357
-
358
-static SRes SzReadPackInfo(
359
-    CSzData *sd,
360
-    UInt64 *dataOffset,
361
-    UInt32 *numPackStreams,
362
-    UInt64 **packSizes,
363
-    Byte **packCRCsDefined,
364
-    UInt32 **packCRCs,
365
-    ISzAlloc *alloc)
366
-{
367
-  UInt32 i;
368
-  RINOK(SzReadNumber(sd, dataOffset));
369
-  RINOK(SzReadNumber32(sd, numPackStreams));
370
-
371
-  RINOK(SzWaitAttribute(sd, k7zIdSize));
372
-
373
-  MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc);
374
-
375
-  for (i = 0; i < *numPackStreams; i++)
376
-  {
377
-    RINOK(SzReadNumber(sd, (*packSizes) + i));
378
-  }
379
-
380
-  for (;;)
381
-  {
382
-    UInt64 type;
383
-    RINOK(SzReadID(sd, &type));
384
-    if (type == k7zIdEnd)
385
-      break;
386
-    if (type == k7zIdCRC)
387
-    {
388
-      RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc));
389
-      continue;
390
-    }
391
-    RINOK(SzSkeepData(sd));
392
-  }
393
-  if (*packCRCsDefined == 0)
394
-  {
395
-    MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc);
396
-    MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc);
397
-    for (i = 0; i < *numPackStreams; i++)
398
-    {
399
-      (*packCRCsDefined)[i] = 0;
400
-      (*packCRCs)[i] = 0;
401
-    }
402
-  }
403
-  return SZ_OK;
404
-}
405
-
406
-static SRes SzReadSwitch(CSzData *sd)
407
-{
408
-  Byte external;
409
-  RINOK(SzReadByte(sd, &external));
410
-  return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
411
-}
412
-
413
-static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)
414
-{
415
-  UInt32 numCoders, numBindPairs, numPackStreams, i;
416
-  UInt32 numInStreams = 0, numOutStreams = 0;
417
-  
418
-  RINOK(SzReadNumber32(sd, &numCoders));
419
-  if (numCoders > NUM_FOLDER_CODERS_MAX)
420
-    return SZ_ERROR_UNSUPPORTED;
421
-  folder->NumCoders = numCoders;
422
-  
423
-  MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc);
424
-
425
-  for (i = 0; i < numCoders; i++)
426
-    SzCoderInfo_Init(folder->Coders + i);
427
-
428
-  for (i = 0; i < numCoders; i++)
429
-  {
430
-    Byte mainByte;
431
-    CSzCoderInfo *coder = folder->Coders + i;
432
-    {
433
-      unsigned idSize, j;
434
-      Byte longID[15];
435
-      RINOK(SzReadByte(sd, &mainByte));
436
-      idSize = (unsigned)(mainByte & 0xF);
437
-      RINOK(SzReadBytes(sd, longID, idSize));
438
-      if (idSize > sizeof(coder->MethodID))
439
-        return SZ_ERROR_UNSUPPORTED;
440
-      coder->MethodID = 0;
441
-      for (j = 0; j < idSize; j++)
442
-        coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j);
443
-
444
-      if ((mainByte & 0x10) != 0)
445
-      {
446
-        RINOK(SzReadNumber32(sd, &coder->NumInStreams));
447
-        RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
448
-        if (coder->NumInStreams > NUM_CODER_STREAMS_MAX ||
449
-            coder->NumOutStreams > NUM_CODER_STREAMS_MAX)
450
-          return SZ_ERROR_UNSUPPORTED;
451
-      }
452
-      else
453
-      {
454
-        coder->NumInStreams = 1;
455
-        coder->NumOutStreams = 1;
456
-      }
457
-      if ((mainByte & 0x20) != 0)
458
-      {
459
-        UInt64 propertiesSize = 0;
460
-        RINOK(SzReadNumber(sd, &propertiesSize));
461
-        if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc))
462
-          return SZ_ERROR_MEM;
463
-        RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize));
464
-      }
465
-    }
466
-    while ((mainByte & 0x80) != 0)
467
-    {
468
-      RINOK(SzReadByte(sd, &mainByte));
469
-      RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
470
-      if ((mainByte & 0x10) != 0)
471
-      {
472
-        UInt32 n;
473
-        RINOK(SzReadNumber32(sd, &n));
474
-        RINOK(SzReadNumber32(sd, &n));
475
-      }
476
-      if ((mainByte & 0x20) != 0)
477
-      {
478
-        UInt64 propertiesSize = 0;
479
-        RINOK(SzReadNumber(sd, &propertiesSize));
480
-        RINOK(SzSkeepDataSize(sd, propertiesSize));
481
-      }
482
-    }
483
-    numInStreams += coder->NumInStreams;
484
-    numOutStreams += coder->NumOutStreams;
485
-  }
486
-
487
-  if (numOutStreams == 0)
488
-    return SZ_ERROR_UNSUPPORTED;
489
-
490
-  folder->NumBindPairs = numBindPairs = numOutStreams - 1;
491
-  MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);
492
-
493
-  for (i = 0; i < numBindPairs; i++)
494
-  {
495
-    CBindPair *bp = folder->BindPairs + i;
496
-    RINOK(SzReadNumber32(sd, &bp->InIndex));
497
-    RINOK(SzReadNumber32(sd, &bp->OutIndex));
498
-  }
499
-
500
-  if (numInStreams < numBindPairs)
501
-    return SZ_ERROR_UNSUPPORTED;
502
-
503
-  folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs;
504
-  MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc);
505
-
506
-  if (numPackStreams == 1)
507
-  {
508
-    for (i = 0; i < numInStreams ; i++)
509
-      if (SzFolder_FindBindPairForInStream(folder, i) < 0)
510
-        break;
511
-    if (i == numInStreams)
512
-      return SZ_ERROR_UNSUPPORTED;
513
-    folder->PackStreams[0] = i;
514
-  }
515
-  else
516
-    for (i = 0; i < numPackStreams; i++)
517
-    {
518
-      RINOK(SzReadNumber32(sd, folder->PackStreams + i));
519
-    }
520
-  return SZ_OK;
521
-}
522
-
523
-static SRes SzReadUnpackInfo(
524
-    CSzData *sd,
525
-    UInt32 *numFolders,
526
-    CSzFolder **folders,  /* for alloc */
527
-    ISzAlloc *alloc,
528
-    ISzAlloc *allocTemp)
529
-{
530
-  UInt32 i;
531
-  RINOK(SzWaitAttribute(sd, k7zIdFolder));
532
-  RINOK(SzReadNumber32(sd, numFolders));
533
-  {
534
-    RINOK(SzReadSwitch(sd));
535
-
536
-    MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc);
537
-
538
-    for (i = 0; i < *numFolders; i++)
539
-      SzFolder_Init((*folders) + i);
540
-
541
-    for (i = 0; i < *numFolders; i++)
542
-    {
543
-      RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc));
544
-    }
545
-  }
546
-
547
-  RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize));
548
-
549
-  for (i = 0; i < *numFolders; i++)
550
-  {
551
-    UInt32 j;
552
-    CSzFolder *folder = (*folders) + i;
553
-    UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder);
554
-
555
-    MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc);
556
-
557
-    for (j = 0; j < numOutStreams; j++)
558
-    {
559
-      RINOK(SzReadNumber(sd, folder->UnpackSizes + j));
560
-    }
561
-  }
562
-
563
-  for (;;)
564
-  {
565
-    UInt64 type;
566
-    RINOK(SzReadID(sd, &type));
567
-    if (type == k7zIdEnd)
568
-      return SZ_OK;
569
-    if (type == k7zIdCRC)
570
-    {
571
-      SRes res;
572
-      Byte *crcsDefined = 0;
573
-      UInt32 *crcs = 0;
574
-      res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp);
575
-      if (res == SZ_OK)
576
-      {
577
-        for (i = 0; i < *numFolders; i++)
578
-        {
579
-          CSzFolder *folder = (*folders) + i;
580
-          folder->UnpackCRCDefined = crcsDefined[i];
581
-          folder->UnpackCRC = crcs[i];
582
-        }
583
-      }
584
-      IAlloc_Free(allocTemp, crcs);
585
-      IAlloc_Free(allocTemp, crcsDefined);
586
-      RINOK(res);
587
-      continue;
588
-    }
589
-    RINOK(SzSkeepData(sd));
590
-  }
591
-}
592
-
593
-static SRes SzReadSubStreamsInfo(
594
-    CSzData *sd,
595
-    UInt32 numFolders,
596
-    CSzFolder *folders,
597
-    UInt32 *numUnpackStreams,
598
-    UInt64 **unpackSizes,
599
-    Byte **digestsDefined,
600
-    UInt32 **digests,
601
-    ISzAlloc *allocTemp)
602
-{
603
-  UInt64 type = 0;
604
-  UInt32 i;
605
-  UInt32 si = 0;
606
-  UInt32 numDigests = 0;
607
-
608
-  for (i = 0; i < numFolders; i++)
609
-    folders[i].NumUnpackStreams = 1;
610
-  *numUnpackStreams = numFolders;
611
-
612
-  for (;;)
613
-  {
614
-    RINOK(SzReadID(sd, &type));
615
-    if (type == k7zIdNumUnpackStream)
616
-    {
617
-      *numUnpackStreams = 0;
618
-      for (i = 0; i < numFolders; i++)
619
-      {
620
-        UInt32 numStreams;
621
-        RINOK(SzReadNumber32(sd, &numStreams));
622
-        folders[i].NumUnpackStreams = numStreams;
623
-        *numUnpackStreams += numStreams;
624
-      }
625
-      continue;
626
-    }
627
-    if (type == k7zIdCRC || type == k7zIdSize)
628
-      break;
629
-    if (type == k7zIdEnd)
630
-      break;
631
-    RINOK(SzSkeepData(sd));
632
-  }
633
-
634
-  if (*numUnpackStreams == 0)
635
-  {
636
-    *unpackSizes = 0;
637
-    *digestsDefined = 0;
638
-    *digests = 0;
639
-  }
640
-  else
641
-  {
642
-    *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64));
643
-    RINOM(*unpackSizes);
644
-    *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte));
645
-    RINOM(*digestsDefined);
646
-    *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32));
647
-    RINOM(*digests);
648
-  }
649
-
650
-  for (i = 0; i < numFolders && *unpackSizes; i++)
651
-  {
652
-    /*
653
-    v3.13 incorrectly worked with empty folders
654
-    v4.07: we check that folder is empty
655
-    */
656
-    UInt64 sum = 0;
657
-    UInt32 j;
658
-    UInt32 numSubstreams = folders[i].NumUnpackStreams;
659
-    if (numSubstreams == 0)
660
-      continue;
661
-    if (type == k7zIdSize)
662
-    for (j = 1; j < numSubstreams; j++)
663
-    {
664
-      UInt64 size;
665
-      RINOK(SzReadNumber(sd, &size));
666
-      (*unpackSizes)[si++] = size;
667
-      sum += size;
668
-    }
669
-    (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum;
670
-  }
671
-  if (type == k7zIdSize)
672
-  {
673
-    RINOK(SzReadID(sd, &type));
674
-  }
675
-
676
-  for (i = 0; i < *numUnpackStreams; i++)
677
-  {
678
-    (*digestsDefined)[i] = 0;
679
-    (*digests)[i] = 0;
680
-  }
681
-
682
-
683
-  for (i = 0; i < numFolders; i++)
684
-  {
685
-    UInt32 numSubstreams = folders[i].NumUnpackStreams;
686
-    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
687
-      numDigests += numSubstreams;
688
-  }
689
-
690
- 
691
-  si = 0;
692
-  for (;;)
693
-  {
694
-    if (type == k7zIdCRC)
695
-    {
696
-      int digestIndex = 0;
697
-      Byte *digestsDefined2 = 0;
698
-      UInt32 *digests2 = 0;
699
-      SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp);
700
-      if (res == SZ_OK)
701
-      {
702
-        for (i = 0; i < numFolders; i++)
703
-        {
704
-          CSzFolder *folder = folders + i;
705
-          UInt32 numSubstreams = folder->NumUnpackStreams;
706
-          if (numSubstreams == 1 && folder->UnpackCRCDefined)
707
-          {
708
-            (*digestsDefined)[si] = 1;
709
-            (*digests)[si] = folder->UnpackCRC;
710
-            si++;
711
-          }
712
-          else
713
-          {
714
-            UInt32 j;
715
-            for (j = 0; j < numSubstreams; j++, digestIndex++)
716
-            {
717
-              (*digestsDefined)[si] = digestsDefined2[digestIndex];
718
-              (*digests)[si] = digests2[digestIndex];
719
-              si++;
720
-            }
721
-          }
722
-        }
723
-      }
724
-      IAlloc_Free(allocTemp, digestsDefined2);
725
-      IAlloc_Free(allocTemp, digests2);
726
-      RINOK(res);
727
-    }
728
-    else if (type == k7zIdEnd)
729
-      return SZ_OK;
730
-    else
731
-    {
732
-      RINOK(SzSkeepData(sd));
733
-    }
734
-    RINOK(SzReadID(sd, &type));
735
-  }
736
-}
737
-
738
-
739
-static SRes SzReadStreamsInfo(
740
-    CSzData *sd,
741
-    UInt64 *dataOffset,
742
-    CSzAr *p,
743
-    UInt32 *numUnpackStreams,
744
-    UInt64 **unpackSizes, /* allocTemp */
745
-    Byte **digestsDefined,   /* allocTemp */
746
-    UInt32 **digests,        /* allocTemp */
747
-    ISzAlloc *alloc,
748
-    ISzAlloc *allocTemp)
749
-{
750
-  for (;;)
751
-  {
752
-    UInt64 type;
753
-    RINOK(SzReadID(sd, &type));
754
-    if ((UInt64)(int)type != type)
755
-      return SZ_ERROR_UNSUPPORTED;
756
-    switch((int)type)
757
-    {
758
-      case k7zIdEnd:
759
-        return SZ_OK;
760
-      case k7zIdPackInfo:
761
-      {
762
-        RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams,
763
-            &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc));
764
-        break;
765
-      }
766
-      case k7zIdUnpackInfo:
767
-      {
768
-        RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp));
769
-        break;
770
-      }
771
-      case k7zIdSubStreamsInfo:
772
-      {
773
-        RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders,
774
-            numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp));
775
-        break;
776
-      }
777
-      default:
778
-        return SZ_ERROR_UNSUPPORTED;
779
-    }
780
-  }
781
-}
782
-
783
-Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
784
-
785
-static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc)
786
-{
787
-  UInt32 i;
788
-  for (i = 0; i < numFiles; i++)
789
-  {
790
-    UInt32 len = 0;
791
-    UInt32 pos = 0;
792
-    CSzFileItem *file = files + i;
793
-    while (pos + 2 <= sd->Size)
794
-    {
795
-      int numAdds;
796
-      UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
797
-      pos += 2;
798
-      len++;
799
-      if (value == 0)
800
-        break;
801
-      if (value < 0x80)
802
-        continue;
803
-      if (value >= 0xD800 && value < 0xE000)
804
-      {
805
-        UInt32 c2;
806
-        if (value >= 0xDC00)
807
-          return SZ_ERROR_ARCHIVE;
808
-        if (pos + 2 > sd->Size)
809
-          return SZ_ERROR_ARCHIVE;
810
-        c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
811
-        pos += 2;
812
-        if (c2 < 0xDC00 || c2 >= 0xE000)
813
-          return SZ_ERROR_ARCHIVE;
814
-        value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
815
-      }
816
-      for (numAdds = 1; numAdds < 5; numAdds++)
817
-        if (value < (((UInt32)1) << (numAdds * 5 + 6)))
818
-          break;
819
-      len += numAdds;
820
-    }
821
-
822
-    MY_ALLOC(char, file->Name, (size_t)len, alloc);
823
-
824
-    len = 0;
825
-    while (2 <= sd->Size)
826
-    {
827
-      int numAdds;
828
-      UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
829
-      SzSkeepDataSize(sd, 2);
830
-      if (value < 0x80)
831
-      {
832
-        file->Name[len++] = (char)value;
833
-        if (value == 0)
834
-          break;
835
-        continue;
836
-      }
837
-      if (value >= 0xD800 && value < 0xE000)
838
-      {
839
-        UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
840
-        SzSkeepDataSize(sd, 2);
841
-        value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
842
-      }
843
-      for (numAdds = 1; numAdds < 5; numAdds++)
844
-        if (value < (((UInt32)1) << (numAdds * 5 + 6)))
845
-          break;
846
-      file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
847
-      do
848
-      {
849
-        numAdds--;
850
-        file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
851
-      }
852
-      while (numAdds > 0);
853
-
854
-      len += numAdds;
855
-    }
856
-  }
857
-  return SZ_OK;
858
-}
859
-
860
-static SRes SzReadHeader2(
861
-    CSzArEx *p,   /* allocMain */
862
-    CSzData *sd,
863
-    UInt64 **unpackSizes,  /* allocTemp */
864
-    Byte **digestsDefined,    /* allocTemp */
865
-    UInt32 **digests,         /* allocTemp */
866
-    Byte **emptyStreamVector, /* allocTemp */
867
-    Byte **emptyFileVector,   /* allocTemp */
868
-    Byte **lwtVector,         /* allocTemp */
869
-    ISzAlloc *allocMain,
870
-    ISzAlloc *allocTemp)
871
-{
872
-  UInt64 type;
873
-  UInt32 numUnpackStreams = 0;
874
-  UInt32 numFiles = 0;
875
-  CSzFileItem *files = 0;
876
-  UInt32 numEmptyStreams = 0;
877
-  UInt32 i;
878
-
879
-  RINOK(SzReadID(sd, &type));
880
-
881
-  if (type == k7zIdArchiveProperties)
882
-  {
883
-    RINOK(SzReadArchiveProperties(sd));
884
-    RINOK(SzReadID(sd, &type));
885
-  }
886
- 
887
- 
888
-  if (type == k7zIdMainStreamsInfo)
889
-  {
890
-    RINOK(SzReadStreamsInfo(sd,
891
-        &p->dataPos,
892
-        &p->db,
893
-        &numUnpackStreams,
894
-        unpackSizes,
895
-        digestsDefined,
896
-        digests, allocMain, allocTemp));
897
-    p->dataPos += p->startPosAfterHeader;
898
-    RINOK(SzReadID(sd, &type));
899
-  }
900
-
901
-  if (type == k7zIdEnd)
902
-    return SZ_OK;
903
-  if (type != k7zIdFilesInfo)
904
-    return SZ_ERROR_ARCHIVE;
905
-  
906
-  RINOK(SzReadNumber32(sd, &numFiles));
907
-  p->db.NumFiles = numFiles;
908
-
909
-  MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);
910
-
911
-  p->db.Files = files;
912
-  for (i = 0; i < numFiles; i++)
913
-    SzFile_Init(files + i);
914
-
915
-  for (;;)
916
-  {
917
-    UInt64 type;
918
-    UInt64 size;
919
-    RINOK(SzReadID(sd, &type));
920
-    if (type == k7zIdEnd)
921
-      break;
922
-    RINOK(SzReadNumber(sd, &size));
923
-
924
-    if ((UInt64)(int)type != type)
925
-    {
926
-      RINOK(SzSkeepDataSize(sd, size));
927
-    }
928
-    else
929
-    switch((int)type)
930
-    {
931
-      case k7zIdName:
932
-      {
933
-        RINOK(SzReadSwitch(sd));
934
-        RINOK(SzReadFileNames(sd, numFiles, files, allocMain))
935
-        break;
936
-      }
937
-      case k7zIdEmptyStream:
938
-      {
939
-        RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));
940
-        numEmptyStreams = 0;
941
-        for (i = 0; i < numFiles; i++)
942
-          if ((*emptyStreamVector)[i])
943
-            numEmptyStreams++;
944
-        break;
945
-      }
946
-      case k7zIdEmptyFile:
947
-      {
948
-        RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));
949
-        break;
950
-      }
951
-      case k7zIdMTime:
952
-      {
953
-        RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
954
-        RINOK(SzReadSwitch(sd));
955
-        for (i = 0; i < numFiles; i++)
956
-        {
957
-          CSzFileItem *f = &files[i];
958
-          Byte defined = (*lwtVector)[i];
959
-          f->MTimeDefined = defined;
960
-          f->MTime.Low = f->MTime.High = 0;
961
-          if (defined)
962
-          {
963
-            RINOK(SzReadUInt32(sd, &f->MTime.Low));
964
-            RINOK(SzReadUInt32(sd, &f->MTime.High));
965
-          }
966
-        }
967
-        break;
968
-      }
969
-      default:
970
-      {
971
-        RINOK(SzSkeepDataSize(sd, size));
972
-      }
973
-    }
974
-  }
975
-
976
-  {
977
-    UInt32 emptyFileIndex = 0;
978
-    UInt32 sizeIndex = 0;
979
-    for (i = 0; i < numFiles; i++)
980
-    {
981
-      CSzFileItem *file = files + i;
982
-      file->IsAnti = 0;
983
-      if (*emptyStreamVector == 0)
984
-        file->HasStream = 1;
985
-      else
986
-        file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
987
-      if (file->HasStream)
988
-      {
989
-        file->IsDir = 0;
990
-        file->Size = (*unpackSizes)[sizeIndex];
991
-        file->FileCRC = (*digests)[sizeIndex];
992
-        file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex];
993
-        sizeIndex++;
994
-      }
995
-      else
996
-      {
997
-        if (*emptyFileVector == 0)
998
-          file->IsDir = 1;
999
-        else
1000
-          file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
1001
-        emptyFileIndex++;
1002
-        file->Size = 0;
1003
-        file->FileCRCDefined = 0;
1004
-      }
1005
-    }
1006
-  }
1007
-  return SzArEx_Fill(p, allocMain);
1008
-}
1009
-
1010
-static SRes SzReadHeader(
1011
-    CSzArEx *p,
1012
-    CSzData *sd,
1013
-    ISzAlloc *allocMain,
1014
-    ISzAlloc *allocTemp)
1015
-{
1016
-  UInt64 *unpackSizes = 0;
1017
-  Byte *digestsDefined = 0;
1018
-  UInt32 *digests = 0;
1019
-  Byte *emptyStreamVector = 0;
1020
-  Byte *emptyFileVector = 0;
1021
-  Byte *lwtVector = 0;
1022
-  SRes res = SzReadHeader2(p, sd,
1023
-      &unpackSizes, &digestsDefined, &digests,
1024
-      &emptyStreamVector, &emptyFileVector, &lwtVector,
1025
-      allocMain, allocTemp);
1026
-  IAlloc_Free(allocTemp, unpackSizes);
1027
-  IAlloc_Free(allocTemp, digestsDefined);
1028
-  IAlloc_Free(allocTemp, digests);
1029
-  IAlloc_Free(allocTemp, emptyStreamVector);
1030
-  IAlloc_Free(allocTemp, emptyFileVector);
1031
-  IAlloc_Free(allocTemp, lwtVector);
1032
-  return res;
1033
-}
1034
-
1035
-static SRes SzReadAndDecodePackedStreams2(
1036
-    ILookInStream *inStream,
1037
-    CSzData *sd,
1038
-    CBuf *outBuffer,
1039
-    UInt64 baseOffset,
1040
-    CSzAr *p,
1041
-    UInt64 **unpackSizes,
1042
-    Byte **digestsDefined,
1043
-    UInt32 **digests,
1044
-    ISzAlloc *allocTemp)
1045
-{
1046
-
1047
-  UInt32 numUnpackStreams = 0;
1048
-  UInt64 dataStartPos;
1049
-  CSzFolder *folder;
1050
-  UInt64 unpackSize;
1051
-  SRes res;
1052
-
1053
-  RINOK(SzReadStreamsInfo(sd, &dataStartPos, p,
1054
-      &numUnpackStreams,  unpackSizes, digestsDefined, digests,
1055
-      allocTemp, allocTemp));
1056
-  
1057
-  dataStartPos += baseOffset;
1058
-  if (p->NumFolders != 1)
1059
-    return SZ_ERROR_ARCHIVE;
1060
-
1061
-  folder = p->Folders;
1062
-  unpackSize = SzFolder_GetUnpackSize(folder);
1063
-  
1064
-  RINOK(LookInStream_SeekTo(inStream, dataStartPos));
1065
-
1066
-  if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))
1067
-    return SZ_ERROR_MEM;
1068
-  
1069
-  res = SzDecode(p->PackSizes, folder,
1070
-          inStream, dataStartPos,
1071
-          outBuffer->data, (size_t)unpackSize, allocTemp);
1072
-  RINOK(res);
1073
-  if (folder->UnpackCRCDefined)
1074
-    if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC)
1075
-      return SZ_ERROR_CRC;
1076
-  return SZ_OK;
1077
-}
1078
-
1079
-static SRes SzReadAndDecodePackedStreams(
1080
-    ILookInStream *inStream,
1081
-    CSzData *sd,
1082
-    CBuf *outBuffer,
1083
-    UInt64 baseOffset,
1084
-    ISzAlloc *allocTemp)
1085
-{
1086
-  CSzAr p;
1087
-  UInt64 *unpackSizes = 0;
1088
-  Byte *digestsDefined = 0;
1089
-  UInt32 *digests = 0;
1090
-  SRes res;
1091
-  SzAr_Init(&p);
1092
-  res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
1093
-    &p, &unpackSizes, &digestsDefined, &digests,
1094
-    allocTemp);
1095
-  SzAr_Free(&p, allocTemp);
1096
-  IAlloc_Free(allocTemp, unpackSizes);
1097
-  IAlloc_Free(allocTemp, digestsDefined);
1098
-  IAlloc_Free(allocTemp, digests);
1099
-  return res;
1100
-}
1101
-
1102
-static SRes SzArEx_Open2(
1103
-    CSzArEx *p,
1104
-    ILookInStream *inStream,
1105
-    ISzAlloc *allocMain,
1106
-    ISzAlloc *allocTemp)
1107
-{
1108
-  Byte header[k7zStartHeaderSize];
1109
-  UInt64 nextHeaderOffset, nextHeaderSize;
1110
-  size_t nextHeaderSizeT;
1111
-  UInt32 nextHeaderCRC;
1112
-  CBuf buffer;
1113
-  SRes res;
1114
-
1115
-  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
1116
-
1117
-  if (!TestSignatureCandidate(header))
1118
-    return SZ_ERROR_NO_ARCHIVE;
1119
-  if (header[6] != k7zMajorVersion)
1120
-    return SZ_ERROR_UNSUPPORTED;
1121
-
1122
-  nextHeaderOffset = GetUi64(header + 12);
1123
-  nextHeaderSize = GetUi64(header + 20);
1124
-  nextHeaderCRC = GetUi32(header + 28);
1125
-
1126
-  p->startPosAfterHeader = k7zStartHeaderSize;
1127
-  
1128
-/* aCaB - 2010-02-16 - RECOVERY MODE  
1129
-  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
1130
-    return SZ_ERROR_CRC; */
1131
-  if(!GetUi32(header + 8) && !nextHeaderOffset && !nextHeaderSize && !nextHeaderCRC) {
1132
-    int i, checkSize = 500;
1133
-    Byte buf[500];
1134
-    Int64 curpos=0, endpos=0, readpos;
1135
-    RINOK(inStream->Seek(inStream, &curpos, SZ_SEEK_CUR));
1136
-    RINOK(inStream->Seek(inStream, &endpos, SZ_SEEK_END));
1137
-    if(endpos-curpos < 500) checkSize = endpos-curpos;
1138
-    readpos = endpos - checkSize;
1139
-    RINOK(inStream->Seek(inStream, &readpos, SZ_SEEK_SET));
1140
-    RINOK(LookInStream_Read2(inStream, buf, checkSize, SZ_ERROR_ARCHIVE));
1141
-    for (i = (int)checkSize - 2; i >= 0; i--)
1142
-      if((buf[i] == 0x17 && buf[i + 1] == 0x6) || (buf[i] == 0x01 && buf[i + 1] == 0x04))
1143
-	break;
1144
-    if (i < 0)
1145
-      return SZ_ERROR_ARCHIVE;
1146
-    nextHeaderSize = checkSize - i;
1147
-    nextHeaderOffset = readpos + i;
1148
-    if(nextHeaderOffset < k7zStartHeaderSize)
1149
-      return SZ_ERROR_INPUT_EOF;
1150
-    nextHeaderOffset -= k7zStartHeaderSize;
1151
-    nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
1152
-    RINOK(inStream->Seek(inStream, &curpos, SZ_SEEK_SET));
1153
-  }
1154
-/* aCaB - 2010-02-16 - END OF RECOVERY MODE */
1155
-
1156
-  nextHeaderSizeT = (size_t)nextHeaderSize;
1157
-  if (nextHeaderSizeT != nextHeaderSize)
1158
-    return SZ_ERROR_MEM;
1159
-  if (nextHeaderSizeT == 0)
1160
-    return SZ_OK;
1161
-  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
1162
-      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
1163
-    return SZ_ERROR_NO_ARCHIVE;
1164
-
1165
-  {
1166
-    Int64 pos = 0;
1167
-    RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
1168
-    if ((UInt64)pos < nextHeaderOffset ||
1169
-        (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset ||
1170
-        (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
1171
-      return SZ_ERROR_INPUT_EOF;
1172
-  }
1173
-
1174
-  RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset));
1175
-
1176
-  if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))
1177
-    return SZ_ERROR_MEM;
1178
-
1179
-  res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT);
1180
-  if (res == SZ_OK)
1181
-  {
1182
-    res = SZ_ERROR_ARCHIVE;
1183
-    if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC)
1184
-    {
1185
-      CSzData sd;
1186
-      UInt64 type;
1187
-      sd.Data = buffer.data;
1188
-      sd.Size = buffer.size;
1189
-      res = SzReadID(&sd, &type);
1190
-      if (res == SZ_OK)
1191
-      {
1192
-        if (type == k7zIdEncodedHeader)
1193
-        {
1194
-          CBuf outBuffer;
1195
-          Buf_Init(&outBuffer);
1196
-          res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp);
1197
-          if (res != SZ_OK)
1198
-            Buf_Free(&outBuffer, allocTemp);
1199
-          else
1200
-          {
1201
-            Buf_Free(&buffer, allocTemp);
1202
-            buffer.data = outBuffer.data;
1203
-            buffer.size = outBuffer.size;
1204
-            sd.Data = buffer.data;
1205
-            sd.Size = buffer.size;
1206
-            res = SzReadID(&sd, &type);
1207
-          }
1208
-        }
1209
-      }
1210
-      if (res == SZ_OK)
1211
-      {
1212
-        if (type == k7zIdHeader)
1213
-          res = SzReadHeader(p, &sd, allocMain, allocTemp);
1214
-        else
1215
-          res = SZ_ERROR_UNSUPPORTED;
1216
-      }
1217
-    }
1218
-  }
1219
-  Buf_Free(&buffer, allocTemp);
1220
-  return res;
1221
-}
1222
-
1223
-SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp)
1224
-{
1225
-  SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
1226
-  if (res != SZ_OK)
1227
-    SzArEx_Free(p, allocMain);
1228
-  return res;
1229
-}
1230 1
deleted file mode 100644
... ...
@@ -1,41 +0,0 @@
1
-/* 7zIn.h -- 7z Input functions
2
-2008-11-23 : Igor Pavlov : Public domain */
3
-
4
-#ifndef __7Z_IN_H
5
-#define __7Z_IN_H
6
-
7
-#include "7zHeader.h"
8
-#include "7zItem.h"
9
-
10
-typedef struct
11
-{
12
-  CSzAr db;
13
-  
14
-  UInt64 startPosAfterHeader;
15
-  UInt64 dataPos;
16
-
17
-  UInt32 *FolderStartPackStreamIndex;
18
-  UInt64 *PackStreamStartPositions;
19
-  UInt32 *FolderStartFileIndex;
20
-  UInt32 *FileIndexToFolderIndexMap;
21
-} CSzArEx;
22
-
23
-void SzArEx_Init(CSzArEx *p);
24
-void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
25
-UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
26
-int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
27
-
28
-/*
29
-Errors:
30
-SZ_ERROR_NO_ARCHIVE
31
-SZ_ERROR_ARCHIVE
32
-SZ_ERROR_UNSUPPORTED
33
-SZ_ERROR_MEM
34
-SZ_ERROR_CRC
35
-SZ_ERROR_INPUT_EOF
36
-SZ_ERROR_FAIL
37
-*/
38
-
39
-SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
40
- 
41
-#endif
42 1
deleted file mode 100644
... ...
@@ -1,127 +0,0 @@
1
-/* 7zItem.c -- 7z Items
2
-2008-10-04 : Igor Pavlov : Public domain */
3
-
4
-#include "7zItem.h"
5
-
6
-void SzCoderInfo_Init(CSzCoderInfo *p)
7
-{
8
-  Buf_Init(&p->Props);
9
-}
10
-
11
-void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
12
-{
13
-  Buf_Free(&p->Props, alloc);
14
-  SzCoderInfo_Init(p);
15
-}
16
-
17
-void SzFolder_Init(CSzFolder *p)
18
-{
19
-  p->Coders = 0;
20
-  p->BindPairs = 0;
21
-  p->PackStreams = 0;
22
-  p->UnpackSizes = 0;
23
-  p->NumCoders = 0;
24
-  p->NumBindPairs = 0;
25
-  p->NumPackStreams = 0;
26
-  p->UnpackCRCDefined = 0;
27
-  p->UnpackCRC = 0;
28
-  p->NumUnpackStreams = 0;
29
-}
30
-
31
-void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
32
-{
33
-  UInt32 i;
34
-  if (p->Coders)
35
-    for (i = 0; i < p->NumCoders; i++)
36
-      SzCoderInfo_Free(&p->Coders[i], alloc);
37
-  IAlloc_Free(alloc, p->Coders);
38
-  IAlloc_Free(alloc, p->BindPairs);
39
-  IAlloc_Free(alloc, p->PackStreams);
40
-  IAlloc_Free(alloc, p->UnpackSizes);
41
-  SzFolder_Init(p);
42
-}
43
-
44
-UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
45
-{
46
-  UInt32 result = 0;
47
-  UInt32 i;
48
-  for (i = 0; i < p->NumCoders; i++)
49
-    result += p->Coders[i].NumOutStreams;
50
-  return result;
51
-}
52
-
53
-int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
54
-{
55
-  UInt32 i;
56
-  for (i = 0; i < p->NumBindPairs; i++)
57
-    if (p->BindPairs[i].InIndex == inStreamIndex)
58
-      return i;
59
-  return -1;
60
-}
61
-
62
-
63
-int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
64
-{
65
-  UInt32 i;
66
-  for (i = 0; i < p->NumBindPairs; i++)
67
-    if (p->BindPairs[i].OutIndex == outStreamIndex)
68
-      return i;
69
-  return -1;
70
-}
71
-
72
-UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
73
-{
74
-  int i = (int)SzFolder_GetNumOutStreams(p);
75
-  if (i == 0)
76
-    return 0;
77
-  for (i--; i >= 0; i--)
78
-    if (SzFolder_FindBindPairForOutStream(p, i) < 0)
79
-      return p->UnpackSizes[i];
80
-  /* throw 1; */
81
-  return 0;
82
-}
83
-
84
-void SzFile_Init(CSzFileItem *p)
85
-{
86
-  p->HasStream = 1;
87
-  p->IsDir = 0;
88
-  p->IsAnti = 0;
89
-  p->FileCRCDefined = 0;
90
-  p->MTimeDefined = 0;
91
-  p->Name = 0;
92
-}
93
-
94
-static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
95
-{
96
-  IAlloc_Free(alloc, p->Name);
97
-  SzFile_Init(p);
98
-}
99
-
100
-void SzAr_Init(CSzAr *p)
101
-{
102
-  p->PackSizes = 0;
103
-  p->PackCRCsDefined = 0;
104
-  p->PackCRCs = 0;
105
-  p->Folders = 0;
106
-  p->Files = 0;
107
-  p->NumPackStreams = 0;
108
-  p->NumFolders = 0;
109
-  p->NumFiles = 0;
110
-}
111
-
112
-void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
113
-{
114
-  UInt32 i;
115
-  if (p->Folders)
116
-    for (i = 0; i < p->NumFolders; i++)
117
-      SzFolder_Free(&p->Folders[i], alloc);
118
-  if (p->Files)
119
-    for (i = 0; i < p->NumFiles; i++)
120
-      SzFile_Free(&p->Files[i], alloc);
121
-  IAlloc_Free(alloc, p->PackSizes);
122
-  IAlloc_Free(alloc, p->PackCRCsDefined);
123
-  IAlloc_Free(alloc, p->PackCRCs);
124
-  IAlloc_Free(alloc, p->Folders);
125
-  IAlloc_Free(alloc, p->Files);
126
-  SzAr_Init(p);
127
-}
128 1
deleted file mode 100644
... ...
@@ -1,84 +0,0 @@
1
-/* 7zItem.h -- 7z Items
2
-2008-10-04 : Igor Pavlov : Public domain */
3
-
4
-#ifndef __7Z_ITEM_H
5
-#define __7Z_ITEM_H
6
-
7
-#include "../../7zBuf.h"
8
-
9
-typedef struct
10
-{
11
-  UInt32 NumInStreams;
12
-  UInt32 NumOutStreams;
13
-  UInt64 MethodID;
14
-  CBuf Props;
15
-} CSzCoderInfo;
16
-
17
-void SzCoderInfo_Init(CSzCoderInfo *p);
18
-void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
19
-
20
-typedef struct
21
-{
22
-  UInt32 InIndex;
23
-  UInt32 OutIndex;
24
-} CBindPair;
25
-
26
-typedef struct
27
-{
28
-  CSzCoderInfo *Coders;
29
-  CBindPair *BindPairs;
30
-  UInt32 *PackStreams;
31
-  UInt64 *UnpackSizes;
32
-  UInt32 NumCoders;
33
-  UInt32 NumBindPairs;
34
-  UInt32 NumPackStreams;
35
-  int UnpackCRCDefined;
36
-  UInt32 UnpackCRC;
37
-
38
-  UInt32 NumUnpackStreams;
39
-} CSzFolder;
40
-
41
-void SzFolder_Init(CSzFolder *p);
42
-UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
43
-int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
44
-UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
45
-UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
46
-
47
-typedef struct
48
-{
49
-  UInt32 Low;
50
-  UInt32 High;
51
-} CNtfsFileTime;
52
-
53
-typedef struct
54
-{
55
-  CNtfsFileTime MTime;
56
-  UInt64 Size;
57
-  char *Name;
58
-  UInt32 FileCRC;
59
-
60
-  Byte HasStream;
61
-  Byte IsDir;
62
-  Byte IsAnti;
63
-  Byte FileCRCDefined;
64
-  Byte MTimeDefined;
65
-} CSzFileItem;
66
-
67
-void SzFile_Init(CSzFileItem *p);
68
-
69
-typedef struct
70
-{
71
-  UInt64 *PackSizes;
72
-  Byte *PackCRCsDefined;
73
-  UInt32 *PackCRCs;
74
-  CSzFolder *Folders;
75
-  CSzFileItem *Files;
76
-  UInt32 NumPackStreams;
77
-  UInt32 NumFolders;
78
-  UInt32 NumFiles;
79
-} CSzAr;
80
-
81
-void SzAr_Init(CSzAr *p);
82
-void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
83
-
84
-#endif
... ...
@@ -1,11 +1,15 @@
1 1
 /* Bcj2.h -- Converter for x86 code (BCJ2)
2
-2008-10-04 : Igor Pavlov : Public domain */
2
+2009-02-07 : Igor Pavlov : Public domain */
3 3
 
4 4
 #ifndef __BCJ2_H
5 5
 #define __BCJ2_H
6 6
 
7 7
 #include "Types.h"
8 8
 
9
+#ifdef __cplusplus
10
+extern "C" {
11
+#endif
12
+
9 13
 /*
10 14
 Conditions:
11 15
   outSize <= FullOutputSize,
... ...
@@ -27,4 +31,8 @@ int Bcj2_Decode(
27 27
     const Byte *buf3, SizeT size3,
28 28
     Byte *outBuf, SizeT outSize);
29 29
 
30
+#ifdef __cplusplus
31
+}
32
+#endif
33
+
30 34
 #endif
... ...
@@ -1,5 +1,5 @@
1 1
 /* Bra.c -- Converters for RISC code
2
-2008-10-04 : Igor Pavlov : Public domain */
2
+2010-04-16 : Igor Pavlov : Public domain */
3 3
 
4 4
 #include "Bra.h"
5 5
 
... ...
@@ -1,11 +1,15 @@
1 1
 /* Bra.h -- Branch converters for executables
2
-2008-10-04 : Igor Pavlov : Public domain */
2
+2009-02-07 : Igor Pavlov : Public domain */
3 3
 
4 4
 #ifndef __BRA_H
5 5
 #define __BRA_H
6 6
 
7 7
 #include "Types.h"
8 8
 
9
+#ifdef __cplusplus
10
+extern "C" {
11
+#endif
12
+
9 13
 /*
10 14
 These functions convert relative addresses to absolute addresses
11 15
 in CALL instructions to increase the compression ratio.
... ...
@@ -57,4 +61,8 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
57 57
 SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
58 58
 SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
59 59
 
60
+#ifdef __cplusplus
61
+}
62
+#endif
63
+
60 64
 #endif
61 65
deleted file mode 100644
... ...
@@ -1,67 +0,0 @@
1
-/* BraIA64.c -- Converter for IA-64 code
2
-2008-10-04 : Igor Pavlov : Public domain */
3
-
4
-#include "Bra.h"
5
-
6
-static const Byte kBranchTable[32] =
7
-{
8
-  0, 0, 0, 0, 0, 0, 0, 0,
9
-  0, 0, 0, 0, 0, 0, 0, 0,
10
-  4, 4, 6, 6, 0, 0, 7, 7,
11
-  4, 4, 0, 0, 4, 4, 0, 0
12
-};
13
-
14
-SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
15
-{
16
-  SizeT i;
17
-  if (size < 16)
18
-    return 0;
19
-  size -= 16;
20
-  for (i = 0; i <= size; i += 16)
21
-  {
22
-    UInt32 instrTemplate = data[i] & 0x1F;
23
-    UInt32 mask = kBranchTable[instrTemplate];
24
-    UInt32 bitPos = 5;
25
-    int slot;
26
-    for (slot = 0; slot < 3; slot++, bitPos += 41)
27
-    {
28
-      UInt32 bytePos, bitRes;
29
-      UInt64 instruction, instNorm;
30
-      int j;
31
-      if (((mask >> slot) & 1) == 0)
32
-        continue;
33
-      bytePos = (bitPos >> 3);
34
-      bitRes = bitPos & 0x7;
35
-      instruction = 0;
36
-      for (j = 0; j < 6; j++)
37
-        instruction += (UInt64)data[i + j + bytePos] << (8 * j);
38
-
39
-      instNorm = instruction >> bitRes;
40
-      if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0)
41
-      {
42
-        UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
43
-        UInt32 dest;
44
-        src |= ((UInt32)(instNorm >> 36) & 1) << 20;
45
-        
46
-        src <<= 4;
47
-        
48
-        if (encoding)
49
-          dest = ip + (UInt32)i + src;
50
-        else
51
-          dest = src - (ip + (UInt32)i);
52
-        
53
-        dest >>= 4;
54
-        
55
-        instNorm &= ~((UInt64)(0x8FFFFF) << 13);
56
-        instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);
57
-        instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));
58
-        
59
-        instruction &= (1 << bitRes) - 1;
60
-        instruction |= (instNorm << bitRes);
61
-        for (j = 0; j < 6; j++)
62
-          data[i + j + bytePos] = (Byte)(instruction >> (8 * j));
63
-      }
64
-    }
65
-  }
66
-  return i;
67
-}
... ...
@@ -1,69 +1,37 @@
1
-/* CpuArch.h
2
-2008-08-05
3
-Igor Pavlov
4
-Public domain */
1
+/* CpuArch.h -- CPU specific code
2
+2010-10-26: Igor Pavlov : Public domain */
5 3
 
6
-#ifndef __CPUARCH_H
7
-#define __CPUARCH_H
4
+#ifndef __CPU_ARCH_H
5
+#define __CPU_ARCH_H
8 6
 
9
-/*
10
-LITTLE_ENDIAN_UNALIGN means:
11
-  1) CPU is LITTLE_ENDIAN
12
-  2) it's allowed to make unaligned memory accesses
13
-if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know
14
-about these properties of platform.
15
-*/
16
-
17
-#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
18
-#define LITTLE_ENDIAN_UNALIGN
19
-#endif
7
+#include "Types.h"
8
+#include "others.h"
20 9
 
21
-#ifdef LITTLE_ENDIAN_UNALIGN
10
+EXTERN_C_BEGIN
22 11
 
23
-#define GetUi16(p) (*(const UInt16 *)(p))
24
-#define GetUi32(p) (*(const UInt32 *)(p))
25
-#define GetUi64(p) (*(const UInt64 *)(p))
26
-#define SetUi32(p, d) *(UInt32 *)(p) = (d);
27
-
28
-#else
12
+/*
13
+MY_CPU_LE means that CPU is LITTLE ENDIAN.
14
+If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
29 15
 
30
-#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
16
+MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
17
+If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
18
+*/
31 19
 
32
-#define GetUi32(p) ( \
33
-             ((const Byte *)(p))[0]        | \
34
-    ((UInt32)((const Byte *)(p))[1] <<  8) | \
35
-    ((UInt32)((const Byte *)(p))[2] << 16) | \
36
-    ((UInt32)((const Byte *)(p))[3] << 24))
20
+#define GetUi16(p) (cli_readint16(p))
21
+#define GetUi32(p) (cli_readint32(p))
37 22
 
38 23
 #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
39 24
 
40
-#define SetUi32(p, d) { UInt32 _x_ = (d); \
25
+#define SetUi16(p, d) { UInt32 _x_ = (d); \
41 26
     ((Byte *)(p))[0] = (Byte)_x_; \
42
-    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
43
-    ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
44
-    ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
27
+    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
45 28
 
46
-#endif
47
-
48
-#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
49
-
50
-#pragma intrinsic(_byteswap_ulong)
51
-#pragma intrinsic(_byteswap_uint64)
52
-#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
53
-#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
54
-
55
-#else
29
+#define SetUi32(p, d) (cli_writeint32(p, d))
56 30
 
57
-#define GetBe32(p) ( \
58
-    ((UInt32)((const Byte *)(p))[0] << 24) | \
59
-    ((UInt32)((const Byte *)(p))[1] << 16) | \
60
-    ((UInt32)((const Byte *)(p))[2] <<  8) | \
61
-             ((const Byte *)(p))[3] )
62
-
63
-#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
64
-
65
-#endif
31
+#define SetUi64(p, d) { UInt64 _x64_ = (d); \
32
+    SetUi32(p, (UInt32)_x64_); \
33
+    SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
66 34
 
67
-#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
35
+EXTERN_C_END
68 36
 
69 37
 #endif
70 38
new file mode 100644
... ...
@@ -0,0 +1,356 @@
0
+/* Lzma2Dec.c -- LZMA2 Decoder
1
+2009-05-03 : Igor Pavlov : Public domain */
2
+
3
+/* #define SHOW_DEBUG_INFO */
4
+
5
+#ifdef SHOW_DEBUG_INFO
6
+#include <stdio.h>
7
+#endif
8
+
9
+#include <string.h>
10
+
11
+#include "Lzma2Dec.h"
12
+
13
+/*
14
+00000000  -  EOS
15
+00000001 U U  -  Uncompressed Reset Dic
16
+00000010 U U  -  Uncompressed No Reset
17
+100uuuuu U U P P  -  LZMA no reset
18
+101uuuuu U U P P  -  LZMA reset state
19
+110uuuuu U U P P S  -  LZMA reset state + new prop
20
+111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic
21
+
22
+  u, U - Unpack Size
23
+  P - Pack Size
24
+  S - Props
25
+*/
26
+
27
+#define LZMA2_CONTROL_LZMA (1 << 7)
28
+#define LZMA2_CONTROL_COPY_NO_RESET 2
29
+#define LZMA2_CONTROL_COPY_RESET_DIC 1
30
+#define LZMA2_CONTROL_EOF 0
31
+
32
+#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
33
+
34
+#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
35
+#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
36
+
37
+#define LZMA2_LCLP_MAX 4
38
+#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
39
+
40
+#ifdef SHOW_DEBUG_INFO
41
+#define PRF(x) x
42
+#else
43
+#define PRF(x)
44
+#endif
45
+
46
+typedef enum
47
+{
48
+  LZMA2_STATE_CONTROL,
49
+  LZMA2_STATE_UNPACK0,
50
+  LZMA2_STATE_UNPACK1,
51
+  LZMA2_STATE_PACK0,
52
+  LZMA2_STATE_PACK1,
53
+  LZMA2_STATE_PROP,
54
+  LZMA2_STATE_DATA,
55
+  LZMA2_STATE_DATA_CONT,
56
+  LZMA2_STATE_FINISHED,
57
+  LZMA2_STATE_ERROR
58
+} ELzma2State;
59
+
60
+static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
61
+{
62
+  UInt32 dicSize;
63
+  if (prop > 40)
64
+    return SZ_ERROR_UNSUPPORTED;
65
+  dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
66
+  props[0] = (Byte)LZMA2_LCLP_MAX;
67
+  props[1] = (Byte)(dicSize);
68
+  props[2] = (Byte)(dicSize >> 8);
69
+  props[3] = (Byte)(dicSize >> 16);
70
+  props[4] = (Byte)(dicSize >> 24);
71
+  return SZ_OK;
72
+}
73
+
74
+SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
75
+{
76
+  Byte props[LZMA_PROPS_SIZE];
77
+  RINOK(Lzma2Dec_GetOldProps(prop, props));
78
+  return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
79
+}
80
+
81
+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
82
+{
83
+  Byte props[LZMA_PROPS_SIZE];
84
+  RINOK(Lzma2Dec_GetOldProps(prop, props));
85
+  return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
86
+}
87
+
88
+void Lzma2Dec_Init(CLzma2Dec *p)
89
+{
90
+  p->state = LZMA2_STATE_CONTROL;
91
+  p->needInitDic = True;
92
+  p->needInitState = True;
93
+  p->needInitProp = True;
94
+  LzmaDec_Init(&p->decoder);
95
+}
96
+
97
+static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
98
+{
99
+  switch(p->state)
100
+  {
101
+    case LZMA2_STATE_CONTROL:
102
+      p->control = b;
103
+      PRF(printf("\n %4X ", p->decoder.dicPos));
104
+      PRF(printf(" %2X", b));
105
+      if (p->control == 0)
106
+        return LZMA2_STATE_FINISHED;
107
+      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
108
+      {
109
+        if ((p->control & 0x7F) > 2)
110
+          return LZMA2_STATE_ERROR;
111
+        p->unpackSize = 0;
112
+      }
113
+      else
114
+        p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
115
+      return LZMA2_STATE_UNPACK0;
116
+    
117
+    case LZMA2_STATE_UNPACK0:
118
+      p->unpackSize |= (UInt32)b << 8;
119
+      return LZMA2_STATE_UNPACK1;
120
+    
121
+    case LZMA2_STATE_UNPACK1:
122
+      p->unpackSize |= (UInt32)b;
123
+      p->unpackSize++;
124
+      PRF(printf(" %8d", p->unpackSize));
125
+      return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
126
+    
127
+    case LZMA2_STATE_PACK0:
128
+      p->packSize = (UInt32)b << 8;
129
+      return LZMA2_STATE_PACK1;
130
+
131
+    case LZMA2_STATE_PACK1:
132
+      p->packSize |= (UInt32)b;
133
+      p->packSize++;
134
+      PRF(printf(" %8d", p->packSize));
135
+      return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
136
+        (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
137
+
138
+    case LZMA2_STATE_PROP:
139
+    {
140
+      int lc, lp;
141
+      if (b >= (9 * 5 * 5))
142
+        return LZMA2_STATE_ERROR;
143
+      lc = b % 9;
144
+      b /= 9;
145
+      p->decoder.prop.pb = b / 5;
146
+      lp = b % 5;
147
+      if (lc + lp > LZMA2_LCLP_MAX)
148
+        return LZMA2_STATE_ERROR;
149
+      p->decoder.prop.lc = lc;
150
+      p->decoder.prop.lp = lp;
151
+      p->needInitProp = False;
152
+      return LZMA2_STATE_DATA;
153
+    }
154
+  }
155
+  return LZMA2_STATE_ERROR;
156
+}
157
+
158
+static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
159
+{
160
+  memcpy(p->dic + p->dicPos, src, size);
161
+  p->dicPos += size;
162
+  if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
163
+    p->checkDicSize = p->prop.dicSize;
164
+  p->processedPos += (UInt32)size;
165
+}
166
+
167
+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
168
+
169
+SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
170
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
171
+{
172
+  SizeT inSize = *srcLen;
173
+  *srcLen = 0;
174
+  *status = LZMA_STATUS_NOT_SPECIFIED;
175
+
176
+  while (p->state != LZMA2_STATE_FINISHED)
177
+  {
178
+    SizeT dicPos = p->decoder.dicPos;
179
+    if (p->state == LZMA2_STATE_ERROR)
180
+      return SZ_ERROR_DATA;
181
+    if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
182
+    {
183
+      *status = LZMA_STATUS_NOT_FINISHED;
184
+      return SZ_OK;
185
+    }
186
+    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
187
+    {
188
+      if (*srcLen == inSize)
189
+      {
190
+        *status = LZMA_STATUS_NEEDS_MORE_INPUT;
191
+        return SZ_OK;
192
+      }
193
+      (*srcLen)++;
194
+      p->state = Lzma2Dec_UpdateState(p, *src++);
195
+      continue;
196
+    }
197
+    {
198
+      SizeT destSizeCur = dicLimit - dicPos;
199
+      SizeT srcSizeCur = inSize - *srcLen;
200
+      ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
201
+      
202
+      if (p->unpackSize <= destSizeCur)
203
+      {
204
+        destSizeCur = (SizeT)p->unpackSize;
205
+        curFinishMode = LZMA_FINISH_END;
206
+      }
207
+
208
+      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
209
+      {
210
+        if (*srcLen == inSize)
211
+        {
212
+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
213
+          return SZ_OK;
214
+        }
215
+
216
+        if (p->state == LZMA2_STATE_DATA)
217
+        {
218
+          Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
219
+          if (initDic)
220
+            p->needInitProp = p->needInitState = True;
221
+          else if (p->needInitDic)
222
+            return SZ_ERROR_DATA;
223
+          p->needInitDic = False;
224
+          LzmaDec_InitDicAndState(&p->decoder, initDic, False);
225
+        }
226
+
227
+        if (srcSizeCur > destSizeCur)
228
+          srcSizeCur = destSizeCur;
229
+
230
+        if (srcSizeCur == 0)
231
+          return SZ_ERROR_DATA;
232
+
233
+        LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
234
+
235
+        src += srcSizeCur;
236
+        *srcLen += srcSizeCur;
237
+        p->unpackSize -= (UInt32)srcSizeCur;
238
+        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
239
+      }
240
+      else
241
+      {
242
+        SizeT outSizeProcessed;
243
+        SRes res;
244
+
245
+        if (p->state == LZMA2_STATE_DATA)
246
+        {
247
+          int mode = LZMA2_GET_LZMA_MODE(p);
248
+          Bool initDic = (mode == 3);
249
+          Bool initState = (mode > 0);
250
+          if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
251
+            return SZ_ERROR_DATA;
252
+          
253
+          LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
254
+          p->needInitDic = False;
255
+          p->needInitState = False;
256
+          p->state = LZMA2_STATE_DATA_CONT;
257
+        }
258
+        if (srcSizeCur > p->packSize)
259
+          srcSizeCur = (SizeT)p->packSize;
260
+          
261
+        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
262
+        
263
+        src += srcSizeCur;
264
+        *srcLen += srcSizeCur;
265
+        p->packSize -= (UInt32)srcSizeCur;
266
+
267
+        outSizeProcessed = p->decoder.dicPos - dicPos;
268
+        p->unpackSize -= (UInt32)outSizeProcessed;
269
+
270
+        RINOK(res);
271
+        if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
272
+          return res;
273
+
274
+        if (srcSizeCur == 0 && outSizeProcessed == 0)
275
+        {
276
+          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
277
+              p->unpackSize != 0 || p->packSize != 0)
278
+            return SZ_ERROR_DATA;
279
+          p->state = LZMA2_STATE_CONTROL;
280
+        }
281
+        if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
282
+          *status = LZMA_STATUS_NOT_FINISHED;
283
+      }
284
+    }
285
+  }
286
+  *status = LZMA_STATUS_FINISHED_WITH_MARK;
287
+  return SZ_OK;
288
+}
289
+
290
+SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
291
+{
292
+  SizeT outSize = *destLen, inSize = *srcLen;
293
+  *srcLen = *destLen = 0;
294
+  for (;;)
295
+  {
296
+    SizeT srcSizeCur = inSize, outSizeCur, dicPos;
297
+    ELzmaFinishMode curFinishMode;
298
+    SRes res;
299
+    if (p->decoder.dicPos == p->decoder.dicBufSize)
300
+      p->decoder.dicPos = 0;
301
+    dicPos = p->decoder.dicPos;
302
+    if (outSize > p->decoder.dicBufSize - dicPos)
303
+    {
304
+      outSizeCur = p->decoder.dicBufSize;
305
+      curFinishMode = LZMA_FINISH_ANY;
306
+    }
307
+    else
308
+    {
309
+      outSizeCur = dicPos + outSize;
310
+      curFinishMode = finishMode;
311
+    }
312
+
313
+    res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
314
+    src += srcSizeCur;
315
+    inSize -= srcSizeCur;
316
+    *srcLen += srcSizeCur;
317
+    outSizeCur = p->decoder.dicPos - dicPos;
318
+    memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
319
+    dest += outSizeCur;
320
+    outSize -= outSizeCur;
321
+    *destLen += outSizeCur;
322
+    if (res != 0)
323
+      return res;
324
+    if (outSizeCur == 0 || outSize == 0)
325
+      return SZ_OK;
326
+  }
327
+}
328
+
329
+SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
330
+    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
331
+{
332
+  CLzma2Dec decoder;
333
+  SRes res;
334
+  SizeT outSize = *destLen, inSize = *srcLen;
335
+  Byte props[LZMA_PROPS_SIZE];
336
+
337
+  Lzma2Dec_Construct(&decoder);
338
+
339
+  *destLen = *srcLen = 0;
340
+  *status = LZMA_STATUS_NOT_SPECIFIED;
341
+  decoder.decoder.dic = dest;
342
+  decoder.decoder.dicBufSize = outSize;
343
+
344
+  RINOK(Lzma2Dec_GetOldProps(prop, props));
345
+  RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
346
+  
347
+  *srcLen = inSize;
348
+  res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
349
+  *destLen = decoder.decoder.dicPos;
350
+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
351
+    res = SZ_ERROR_INPUT_EOF;
352
+
353
+  LzmaDec_FreeProbs(&decoder.decoder, alloc);
354
+  return res;
355
+}
0 356
new file mode 100644
... ...
@@ -0,0 +1,84 @@
0
+/* Lzma2Dec.h -- LZMA2 Decoder
1
+2009-05-03 : Igor Pavlov : Public domain */
2
+
3
+#ifndef __LZMA2_DEC_H
4
+#define __LZMA2_DEC_H
5
+
6
+#include "LzmaDec.h"
7
+
8
+#ifdef __cplusplus
9
+extern "C" {
10
+#endif
11
+
12
+/* ---------- State Interface ---------- */
13
+
14
+typedef struct
15
+{
16
+  CLzmaDec decoder;
17
+  UInt32 packSize;
18
+  UInt32 unpackSize;
19
+  int state;
20
+  Byte control;
21
+  Bool needInitDic;
22
+  Bool needInitState;
23
+  Bool needInitProp;
24
+} CLzma2Dec;
25
+
26
+#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
27
+#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
28
+#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
29
+
30
+SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
31
+SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
32
+void Lzma2Dec_Init(CLzma2Dec *p);
33
+
34
+
35
+/*
36
+finishMode:
37
+  It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
38
+  LZMA_FINISH_ANY - use smallest number of input bytes
39
+  LZMA_FINISH_END - read EndOfStream marker after decoding
40
+
41
+Returns:
42
+  SZ_OK
43
+    status:
44
+      LZMA_STATUS_FINISHED_WITH_MARK
45
+      LZMA_STATUS_NOT_FINISHED
46
+      LZMA_STATUS_NEEDS_MORE_INPUT
47
+  SZ_ERROR_DATA - Data error
48
+*/
49
+
50
+SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
51
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
52
+
53
+SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
54
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
55
+
56
+
57
+/* ---------- One Call Interface ---------- */
58
+
59
+/*
60
+finishMode:
61
+  It has meaning only if the decoding reaches output limit (*destLen).
62
+  LZMA_FINISH_ANY - use smallest number of input bytes
63
+  LZMA_FINISH_END - read EndOfStream marker after decoding
64
+
65
+Returns:
66
+  SZ_OK
67
+    status:
68
+      LZMA_STATUS_FINISHED_WITH_MARK
69
+      LZMA_STATUS_NOT_FINISHED
70
+  SZ_ERROR_DATA - Data error
71
+  SZ_ERROR_MEM  - Memory allocation error
72
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
73
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
74
+*/
75
+
76
+SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
77
+    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
78
+
79
+#ifdef __cplusplus
80
+}
81
+#endif
82
+
83
+#endif
... ...
@@ -1,5 +1,5 @@
1 1
 /* LzmaDec.c -- LZMA Decoder
2
-2008-11-06 : Igor Pavlov : Public domain */
2
+2009-09-20 : Igor Pavlov : Public domain */
3 3
 
4 4
 #include "LzmaDec.h"
5 5
 
... ...
@@ -113,12 +113,6 @@
113 113
 StopCompilingDueBUG
114 114
 #endif
115 115
 
116
-static const Byte kLiteralNextStates[kNumStates * 2] =
117
-{
118
-  0, 0, 0, 0, 1, 2, 3,  4,  5,  6,  4,  5,
119
-  7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
120
-};
121
-
122 116
 #define LZMA_DIC_MIN (1 << 12)
123 117
 
124 118
 /* First LZMA-symbol is always decoded.
... ...
@@ -175,6 +169,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
175 175
 
176 176
       if (state < kNumLitStates)
177 177
       {
178
+        state -= (state < 4) ? state : 3;
178 179
         symbol = 1;
179 180
         do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
180 181
       }
... ...
@@ -182,6 +177,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
182 182
       {
183 183
         unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
184 184
         unsigned offs = 0x100;
185
+        state -= (state < 10) ? 3 : 6;
185 186
         symbol = 1;
186 187
         do
187 188
         {
... ...
@@ -196,9 +192,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
196 196
       }
197 197
       dic[dicPos++] = (Byte)symbol;
198 198
       processedPos++;
199
-
200
-      state = kLiteralNextStates[state];
201
-      /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
202 199
       continue;
203 200
     }
204 201
     else
... ...
@@ -378,7 +371,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
378 378
         else if (distance >= checkDicSize)
379 379
           return SZ_ERROR_DATA;
380 380
         state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
381
-        /* state = kLiteralNextStates[state]; */
382 381
       }
383 382
 
384 383
       len += kMatchMinLen;
... ...
@@ -1,11 +1,15 @@
1 1
 /* LzmaDec.h -- LZMA Decoder
2
-2008-10-04 : Igor Pavlov : Public domain */
2
+2009-02-07 : Igor Pavlov : Public domain */
3 3
 
4
-#ifndef __LZMADEC_H
5
-#define __LZMADEC_H
4
+#ifndef __LZMA_DEC_H
5
+#define __LZMA_DEC_H
6 6
 
7 7
 #include "Types.h"
8 8
 
9
+#ifdef __cplusplus
10
+extern "C" {
11
+#endif
12
+
9 13
 /* #define _LZMA_PROB32 */
10 14
 /* _LZMA_PROB32 can increase the speed on some CPUs,
11 15
    but memory usage for CLzmaDec::probs will be doubled in that case */
... ...
@@ -220,4 +224,8 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
220 220
     const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
221 221
     ELzmaStatus *status, ISzAlloc *alloc);
222 222
 
223
+#ifdef __cplusplus
224
+}
225
+#endif
226
+
223 227
 #endif
224 228
new file mode 100644
... ...
@@ -0,0 +1,81 @@
0
+/* Ppmd.h -- PPMD codec common code
1
+2010-03-12 : Igor Pavlov : Public domain
2
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
3
+
4
+#ifndef __PPMD_H
5
+#define __PPMD_H
6
+
7
+#include "Types.h"
8
+#include "CpuArch.h"
9
+
10
+EXTERN_C_BEGIN
11
+
12
+#ifdef MY_CPU_32BIT
13
+  #define PPMD_32BIT
14
+#endif
15
+
16
+#define PPMD_INT_BITS 7
17
+#define PPMD_PERIOD_BITS 7
18
+#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
19
+
20
+#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
21
+#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
22
+#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
23
+#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
24
+
25
+#define PPMD_N1 4
26
+#define PPMD_N2 4
27
+#define PPMD_N3 4
28
+#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
29
+#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
30
+
31
+/* SEE-contexts for PPM-contexts with masked symbols */
32
+typedef struct
33
+{
34
+  UInt16 Summ; /* Freq */
35
+  Byte Shift;  /* Speed of Freq change; low Shift is for fast change */
36
+  Byte Count;  /* Count to next change of Shift */
37
+} CPpmd_See;
38
+
39
+#define Ppmd_See_Update(p)  if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
40
+    { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
41
+
42
+typedef struct
43
+{
44
+  Byte Symbol;
45
+  Byte Freq;
46
+  UInt16 SuccessorLow;
47
+  UInt16 SuccessorHigh;
48
+} CPpmd_State;
49
+
50
+typedef
51
+  #ifdef PPMD_32BIT
52
+    CPpmd_State *
53
+  #else
54
+    UInt32
55
+  #endif
56
+  CPpmd_State_Ref;
57
+
58
+typedef
59
+  #ifdef PPMD_32BIT
60
+    void *
61
+  #else
62
+    UInt32
63
+  #endif
64
+  CPpmd_Void_Ref;
65
+
66
+typedef
67
+  #ifdef PPMD_32BIT
68
+    Byte *
69
+  #else
70
+    UInt32
71
+  #endif
72
+  CPpmd_Byte_Ref;
73
+
74
+#define PPMD_SetAllBitsIn256Bytes(p) \
75
+  { unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
76
+  p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
77
+
78
+EXTERN_C_END
79
+ 
80
+#endif
0 81
new file mode 100644
... ...
@@ -0,0 +1,708 @@
0
+/* Ppmd7.c -- PPMdH codec
1
+2010-03-12 : Igor Pavlov : Public domain
2
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
3
+
4
+#include <memory.h>
5
+
6
+#include "Ppmd7.h"
7
+
8
+const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
9
+static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
10
+
11
+#define MAX_FREQ 124
12
+#define UNIT_SIZE 12
13
+
14
+#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)
15
+#define U2I(nu) (p->Units2Indx[(nu) - 1])
16
+#define I2U(indx) (p->Indx2Units[indx])
17
+
18
+#ifdef PPMD_32BIT
19
+  #define REF(ptr) (ptr)
20
+#else
21
+  #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base))
22
+#endif
23
+
24
+#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))
25
+
26
+#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))
27
+#define STATS(ctx) Ppmd7_GetStats(p, ctx)
28
+#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)
29
+#define SUFFIX(ctx) CTX((ctx)->Suffix)
30
+
31
+typedef CPpmd7_Context * CTX_PTR;
32
+
33
+struct CPpmd7_Node_;
34
+
35
+typedef
36
+  #ifdef PPMD_32BIT
37
+    struct CPpmd7_Node_ *
38
+  #else
39
+    UInt32
40
+  #endif
41
+  CPpmd7_Node_Ref;
42
+
43
+typedef struct CPpmd7_Node_
44
+{
45
+  UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */
46
+  UInt16 NU;
47
+  CPpmd7_Node_Ref Next; /* must be at offset >= 4 */
48
+  CPpmd7_Node_Ref Prev;
49
+} CPpmd7_Node;
50
+
51
+#ifdef PPMD_32BIT
52
+  #define NODE(ptr) (ptr)
53
+#else
54
+  #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs)))
55
+#endif
56
+
57
+void Ppmd7_Construct(CPpmd7 *p)
58
+{
59
+  unsigned i, k, m;
60
+
61
+  p->Base = 0;
62
+
63
+  for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)
64
+  {
65
+    unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);
66
+    do { p->Units2Indx[k++] = (Byte)i; } while(--step);
67
+    p->Indx2Units[i] = (Byte)k;
68
+  }
69
+
70
+  p->NS2BSIndx[0] = (0 << 1);
71
+  p->NS2BSIndx[1] = (1 << 1);
72
+  memset(p->NS2BSIndx + 2, (2 << 1), 9);
73
+  memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);
74
+
75
+  for (i = 0; i < 3; i++)
76
+    p->NS2Indx[i] = (Byte)i;
77
+  for (m = i, k = 1; i < 256; i++)
78
+  {
79
+    p->NS2Indx[i] = (Byte)m;
80
+    if (--k == 0)
81
+      k = (++m) - 2;
82
+  }
83
+
84
+  memset(p->HB2Flag, 0, 0x40);
85
+  memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
86
+}
87
+
88
+void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
89
+{
90
+  alloc->Free(alloc, p->Base);
91
+  p->Size = 0;
92
+  p->Base = 0;
93
+}
94
+
95
+Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
96
+{
97
+  if (p->Base == 0 || p->Size != size)
98
+  {
99
+    Ppmd7_Free(p, alloc);
100
+    p->AlignOffset =
101
+      #ifdef PPMD_32BIT
102
+        (4 - size) & 3;
103
+      #else
104
+        4 - (size & 3);
105
+      #endif
106
+    if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
107
+        #ifndef PPMD_32BIT
108
+        + UNIT_SIZE
109
+        #endif
110
+        )) == 0)
111
+      return False;
112
+    p->Size = size;
113
+  }
114
+  return True;
115
+}
116
+
117
+static void InsertNode(CPpmd7 *p, void *node, unsigned indx)
118
+{
119
+  *((CPpmd_Void_Ref *)node) = p->FreeList[indx];
120
+  p->FreeList[indx] = REF(node);
121
+}
122
+
123
+static void *RemoveNode(CPpmd7 *p, unsigned indx)
124
+{
125
+  CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);
126
+  p->FreeList[indx] = *node;
127
+  return node;
128
+}
129
+
130
+static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)
131
+{
132
+  unsigned i, nu = I2U(oldIndx) - I2U(newIndx);
133
+  ptr = (Byte *)ptr + U2B(I2U(newIndx));
134
+  if (I2U(i = U2I(nu)) != nu)
135
+  {
136
+    unsigned k = I2U(--i);
137
+    InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);
138
+  }
139
+  InsertNode(p, ptr, i);
140
+}
141
+
142
+static void GlueFreeBlocks(CPpmd7 *p)
143
+{
144
+  #ifdef PPMD_32BIT
145
+  CPpmd7_Node headItem;
146
+  CPpmd7_Node_Ref head = &headItem;
147
+  #else
148
+  CPpmd7_Node_Ref head = p->AlignOffset + p->Size;
149
+  #endif
150
+  
151
+  CPpmd7_Node_Ref n = head;
152
+  unsigned i;
153
+
154
+  p->GlueCount = 255;
155
+
156
+  /* create doubly-linked list of free blocks */
157
+  for (i = 0; i < PPMD_NUM_INDEXES; i++)
158
+  {
159
+    UInt16 nu = I2U(i);
160
+    CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];
161
+    p->FreeList[i] = 0;
162
+    while (next != 0)
163
+    {
164
+      CPpmd7_Node *node = NODE(next);
165
+      node->Next = n;
166
+      n = NODE(n)->Prev = next;
167
+      next = *(const CPpmd7_Node_Ref *)node;
168
+      node->Stamp = 0;
169
+      node->NU = (UInt16)nu;
170
+    }
171
+  }
172
+  NODE(head)->Stamp = 1;
173
+  NODE(head)->Next = n;
174
+  NODE(n)->Prev = head;
175
+  if (p->LoUnit != p->HiUnit)
176
+    ((CPpmd7_Node *)p->LoUnit)->Stamp = 1;
177
+  
178
+  /* Glue free blocks */
179
+  while (n != head)
180
+  {
181
+    CPpmd7_Node *node = NODE(n);
182
+    UInt32 nu = (UInt32)node->NU;
183
+    for (;;)
184
+    {
185
+      CPpmd7_Node *node2 = NODE(n) + nu;
186
+      nu += node2->NU;
187
+      if (node2->Stamp != 0 || nu >= 0x10000)
188
+        break;
189
+      NODE(node2->Prev)->Next = node2->Next;
190
+      NODE(node2->Next)->Prev = node2->Prev;
191
+      node->NU = (UInt16)nu;
192
+    }
193
+    n = node->Next;
194
+  }
195
+  
196
+  /* Fill lists of free blocks */
197
+  for (n = NODE(head)->Next; n != head;)
198
+  {
199
+    CPpmd7_Node *node = NODE(n);
200
+    unsigned nu;
201
+    CPpmd7_Node_Ref next = node->Next;
202
+    for (nu = node->NU; nu > 128; nu -= 128, node += 128)
203
+      InsertNode(p, node, PPMD_NUM_INDEXES - 1);
204
+    if (I2U(i = U2I(nu)) != nu)
205
+    {
206
+      unsigned k = I2U(--i);
207
+      InsertNode(p, node + k, nu - k - 1);
208
+    }
209
+    InsertNode(p, node, i);
210
+    n = next;
211
+  }
212
+}
213
+
214
+static void *AllocUnitsRare(CPpmd7 *p, unsigned indx)
215
+{
216
+  unsigned i;
217
+  void *retVal;
218
+  if (p->GlueCount == 0)
219
+  {
220
+    GlueFreeBlocks(p);
221
+    if (p->FreeList[indx] != 0)
222
+      return RemoveNode(p, indx);
223
+  }
224
+  i = indx;
225
+  do
226
+  {
227
+    if (++i == PPMD_NUM_INDEXES)
228
+    {
229
+      UInt32 numBytes = U2B(I2U(indx));
230
+      p->GlueCount--;
231
+      return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL);
232
+    }
233
+  }
234
+  while (p->FreeList[i] == 0);
235
+  retVal = RemoveNode(p, i);
236
+  SplitBlock(p, retVal, i, indx);
237
+  return retVal;
238
+}
239
+
240
+static void *AllocUnits(CPpmd7 *p, unsigned indx)
241
+{
242
+  UInt32 numBytes;
243
+  if (p->FreeList[indx] != 0)
244
+    return RemoveNode(p, indx);
245
+  numBytes = U2B(I2U(indx));
246
+  if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit))
247
+  {
248
+    void *retVal = p->LoUnit;
249
+    p->LoUnit += numBytes;
250
+    return retVal;
251
+  }
252
+  return AllocUnitsRare(p, indx);
253
+}
254
+
255
+#define MyMem12Cpy(dest, src, num) \
256
+  { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
257
+    do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
258
+
259
+static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
260
+{
261
+  unsigned i0 = U2I(oldNU);
262
+  unsigned i1 = U2I(newNU);
263
+  if (i0 == i1)
264
+    return oldPtr;
265
+  if (p->FreeList[i1] != 0)
266
+  {
267
+    void *ptr = RemoveNode(p, i1);
268
+    MyMem12Cpy(ptr, oldPtr, newNU);
269
+    InsertNode(p, oldPtr, i0);
270
+    return ptr;
271
+  }
272
+  SplitBlock(p, oldPtr, i0, i1);
273
+  return oldPtr;
274
+}
275
+
276
+#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16)))
277
+
278
+static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
279
+{
280
+  (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF);
281
+  (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
282
+}
283
+
284
+static void RestartModel(CPpmd7 *p)
285
+{
286
+  unsigned i, k, m;
287
+
288
+  memset(p->FreeList, 0, sizeof(p->FreeList));
289
+  p->Text = p->Base + p->AlignOffset;
290
+  p->HiUnit = p->Text + p->Size;
291
+  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;
292
+  p->GlueCount = 0;
293
+
294
+  p->OrderFall = p->MaxOrder;
295
+  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;
296
+  p->PrevSuccess = 0;
297
+
298
+  p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */
299
+  p->MinContext->Suffix = 0;
300
+  p->MinContext->NumStats = 256;
301
+  p->MinContext->SummFreq = 256 + 1;
302
+  p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */
303
+  p->LoUnit += U2B(256 / 2);
304
+  p->MinContext->Stats = REF(p->FoundState);
305
+  for (i = 0; i < 256; i++)
306
+  {
307
+    CPpmd_State *s = &p->FoundState[i];
308
+    s->Symbol = (Byte)i;
309
+    s->Freq = 1;
310
+    SetSuccessor(s, 0);
311
+  }
312
+
313
+  for (i = 0; i < 128; i++)
314
+    for (k = 0; k < 8; k++)
315
+    {
316
+      UInt16 *dest = p->BinSumm[i] + k;
317
+      UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2));
318
+      for (m = 0; m < 64; m += 8)
319
+        dest[m] = val;
320
+    }
321
+  
322
+  for (i = 0; i < 25; i++)
323
+    for (k = 0; k < 16; k++)
324
+    {
325
+      CPpmd_See *s = &p->See[i][k];
326
+      s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4));
327
+      s->Count = 4;
328
+    }
329
+}
330
+
331
+void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)
332
+{
333
+  p->MaxOrder = maxOrder;
334
+  RestartModel(p);
335
+  p->DummySee.Shift = PPMD_PERIOD_BITS;
336
+  p->DummySee.Summ = 0; /* unused */
337
+  p->DummySee.Count = 64; /* unused */
338
+}
339
+
340
+static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip)
341
+{
342
+  CPpmd_State upState;
343
+  CTX_PTR c = p->MinContext;
344
+  CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);
345
+  CPpmd_State *ps[PPMD7_MAX_ORDER];
346
+  unsigned numPs = 0;
347
+  
348
+  if (!skip)
349
+    ps[numPs++] = p->FoundState;
350
+  
351
+  while (c->Suffix)
352
+  {
353
+    CPpmd_Void_Ref successor;
354
+    CPpmd_State *s;
355
+    c = SUFFIX(c);
356
+    if (c->NumStats != 1)
357
+    {
358
+      for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++);
359
+    }
360
+    else
361
+      s = ONE_STATE(c);
362
+    successor = SUCCESSOR(s);
363
+    if (successor != upBranch)
364
+    {
365
+      c = CTX(successor);
366
+      if (numPs == 0)
367
+        return c;
368
+      break;
369
+    }
370
+    ps[numPs++] = s;
371
+  }
372
+  
373
+  upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch);
374
+  SetSuccessor(&upState, upBranch + 1);
375
+  
376
+  if (c->NumStats == 1)
377
+    upState.Freq = ONE_STATE(c)->Freq;
378
+  else
379
+  {
380
+    UInt32 cf, s0;
381
+    CPpmd_State *s;
382
+    for (s = STATS(c); s->Symbol != upState.Symbol; s++);
383
+    cf = s->Freq - 1;
384
+    s0 = c->SummFreq - c->NumStats - cf;
385
+    upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0))));
386
+  }
387
+
388
+  do
389
+  {
390
+    /* Create Child */
391
+    CTX_PTR c1; /* = AllocContext(p); */
392
+    if (p->HiUnit != p->LoUnit)
393
+      c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE);
394
+    else if (p->FreeList[0] != 0)
395
+      c1 = (CTX_PTR)RemoveNode(p, 0);
396
+    else
397
+    {
398
+      c1 = (CTX_PTR)AllocUnitsRare(p, 0);
399
+      if (!c1)
400
+        return NULL;
401
+    }
402
+    c1->NumStats = 1;
403
+    *ONE_STATE(c1) = upState;
404
+    c1->Suffix = REF(c);
405
+    SetSuccessor(ps[--numPs], REF(c1));
406
+    c = c1;
407
+  }
408
+  while (numPs != 0);
409
+  
410
+  return c;
411
+}
412
+
413
+static void SwapStates(CPpmd_State *t1, CPpmd_State *t2)
414
+{
415
+  CPpmd_State tmp = *t1;
416
+  *t1 = *t2;
417
+  *t2 = tmp;
418
+}
419
+
420
+static void UpdateModel(CPpmd7 *p)
421
+{
422
+  CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState);
423
+  CTX_PTR c;
424
+  unsigned s0, ns;
425
+  
426
+  if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)
427
+  {
428
+    c = SUFFIX(p->MinContext);
429
+    
430
+    if (c->NumStats == 1)
431
+    {
432
+      CPpmd_State *s = ONE_STATE(c);
433
+      if (s->Freq < 32)
434
+        s->Freq++;
435
+    }
436
+    else
437
+    {
438
+      CPpmd_State *s = STATS(c);
439
+      if (s->Symbol != p->FoundState->Symbol)
440
+      {
441
+        do { s++; } while (s->Symbol != p->FoundState->Symbol);
442
+        if (s[0].Freq >= s[-1].Freq)
443
+        {
444
+          SwapStates(&s[0], &s[-1]);
445
+          s--;
446
+        }
447
+      }
448
+      if (s->Freq < MAX_FREQ - 9)
449
+      {
450
+        s->Freq += 2;
451
+        c->SummFreq += 2;
452
+      }
453
+    }
454
+  }
455
+
456
+  if (p->OrderFall == 0)
457
+  {
458
+    p->MinContext = p->MaxContext = CreateSuccessors(p, True);
459
+    if (p->MinContext == 0)
460
+    {
461
+      RestartModel(p);
462
+      return;
463
+    }
464
+    SetSuccessor(p->FoundState, REF(p->MinContext));
465
+    return;
466
+  }
467
+  
468
+  *p->Text++ = p->FoundState->Symbol;
469
+  successor = REF(p->Text);
470
+  if (p->Text >= p->UnitsStart)
471
+  {
472
+    RestartModel(p);
473
+    return;
474
+  }
475
+  
476
+  if (fSuccessor)
477
+  {
478
+    if (fSuccessor <= successor)
479
+    {
480
+      CTX_PTR cs = CreateSuccessors(p, False);
481
+      if (cs == NULL)
482
+      {
483
+        RestartModel(p);
484
+        return;
485
+      }
486
+      fSuccessor = REF(cs);
487
+    }
488
+    if (--p->OrderFall == 0)
489
+    {
490
+      successor = fSuccessor;
491
+      p->Text -= (p->MaxContext != p->MinContext);
492
+    }
493
+  }
494
+  else
495
+  {
496
+    SetSuccessor(p->FoundState, successor);
497
+    fSuccessor = REF(p->MinContext);
498
+  }
499
+  
500
+  s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1);
501
+  
502
+  for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c))
503
+  {
504
+    unsigned ns1;
505
+    UInt32 cf, sf;
506
+    if ((ns1 = c->NumStats) != 1)
507
+    {
508
+      if ((ns1 & 1) == 0)
509
+      {
510
+        /* Expand for one UNIT */
511
+        unsigned oldNU = ns1 >> 1;
512
+        unsigned i = U2I(oldNU);
513
+        if (i != U2I(oldNU + 1))
514
+        {
515
+          void *ptr = AllocUnits(p, i + 1);
516
+          void *oldPtr;
517
+          if (!ptr)
518
+          {
519
+            RestartModel(p);
520
+            return;
521
+          }
522
+          oldPtr = STATS(c);
523
+          MyMem12Cpy(ptr, oldPtr, oldNU);
524
+          InsertNode(p, oldPtr, i);
525
+          c->Stats = STATS_REF(ptr);
526
+        }
527
+      }
528
+      c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1)));
529
+    }
530
+    else
531
+    {
532
+      CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0);
533
+      if (!s)
534
+      {
535
+        RestartModel(p);
536
+        return;
537
+      }
538
+      *s = *ONE_STATE(c);
539
+      c->Stats = REF(s);
540
+      if (s->Freq < MAX_FREQ / 4 - 1)
541
+        s->Freq <<= 1;
542
+      else
543
+        s->Freq = MAX_FREQ - 4;
544
+      c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3));
545
+    }
546
+    cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6);
547
+    sf = (UInt32)s0 + c->SummFreq;
548
+    if (cf < 6 * sf)
549
+    {
550
+      cf = 1 + (cf > sf) + (cf >= 4 * sf);
551
+      c->SummFreq += 3;
552
+    }
553
+    else
554
+    {
555
+      cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);
556
+      c->SummFreq = (UInt16)(c->SummFreq + cf);
557
+    }
558
+    {
559
+      CPpmd_State *s = STATS(c) + ns1;
560
+      SetSuccessor(s, successor);
561
+      s->Symbol = p->FoundState->Symbol;
562
+      s->Freq = (Byte)cf;
563
+      c->NumStats = (UInt16)(ns1 + 1);
564
+    }
565
+  }
566
+  p->MaxContext = p->MinContext = CTX(fSuccessor);
567
+}
568
+  
569
+static void Rescale(CPpmd7 *p)
570
+{
571
+  unsigned i, adder, sumFreq, escFreq;
572
+  CPpmd_State *stats = STATS(p->MinContext);
573
+  CPpmd_State *s = p->FoundState;
574
+  {
575
+    CPpmd_State tmp = *s;
576
+    for (; s != stats; s--)
577
+      s[0] = s[-1];
578
+    *s = tmp;
579
+  }
580
+  escFreq = p->MinContext->SummFreq - s->Freq;
581
+  s->Freq += 4;
582
+  adder = (p->OrderFall != 0);
583
+  s->Freq = (Byte)((s->Freq + adder) >> 1);
584
+  sumFreq = s->Freq;
585
+  
586
+  i = p->MinContext->NumStats - 1;
587
+  do
588
+  {
589
+    escFreq -= (++s)->Freq;
590
+    s->Freq = (Byte)((s->Freq + adder) >> 1);
591
+    sumFreq += s->Freq;
592
+    if (s[0].Freq > s[-1].Freq)
593
+    {
594
+      CPpmd_State *s1 = s;
595
+      CPpmd_State tmp = *s1;
596
+      do
597
+        s1[0] = s1[-1];
598
+      while (--s1 != stats && tmp.Freq > s1[-1].Freq);
599
+      *s1 = tmp;
600
+    }
601
+  }
602
+  while (--i);
603
+  
604
+  if (s->Freq == 0)
605
+  {
606
+    unsigned numStats = p->MinContext->NumStats;
607
+    unsigned n0, n1;
608
+    do { i++; } while ((--s)->Freq == 0);
609
+    escFreq += i;
610
+    p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i);
611
+    if (p->MinContext->NumStats == 1)
612
+    {
613
+      CPpmd_State tmp = *stats;
614
+      do
615
+      {
616
+        tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1));
617
+        escFreq >>= 1;
618
+      }
619
+      while (escFreq > 1);
620
+      InsertNode(p, stats, U2I(((numStats + 1) >> 1)));
621
+      *(p->FoundState = ONE_STATE(p->MinContext)) = tmp;
622
+      return;
623
+    }
624
+    n0 = (numStats + 1) >> 1;
625
+    n1 = (p->MinContext->NumStats + 1) >> 1;
626
+    if (n0 != n1)
627
+      p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));
628
+  }
629
+  p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));
630
+  p->FoundState = STATS(p->MinContext);
631
+}
632
+
633
+CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
634
+{
635
+  CPpmd_See *see;
636
+  unsigned nonMasked = p->MinContext->NumStats - numMasked;
637
+  if (p->MinContext->NumStats != 256)
638
+  {
639
+    see = p->See[p->NS2Indx[nonMasked - 1]] +
640
+        (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) +
641
+        2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) +
642
+        4 * (numMasked > nonMasked) +
643
+        p->HiBitsFlag;
644
+    {
645
+      unsigned r = (see->Summ >> see->Shift);
646
+      see->Summ = (UInt16)(see->Summ - r);
647
+      *escFreq = r + (r == 0);
648
+    }
649
+  }
650
+  else
651
+  {
652
+    see = &p->DummySee;
653
+    *escFreq = 1;
654
+  }
655
+  return see;
656
+}
657
+
658
+static void NextContext(CPpmd7 *p)
659
+{
660
+  CTX_PTR c = CTX(SUCCESSOR(p->FoundState));
661
+  if (p->OrderFall == 0 && (Byte *)c > p->Text)
662
+    p->MinContext = p->MaxContext = c;
663
+  else
664
+    UpdateModel(p);
665
+}
666
+
667
+void Ppmd7_Update1(CPpmd7 *p)
668
+{
669
+  CPpmd_State *s = p->FoundState;
670
+  s->Freq += 4;
671
+  p->MinContext->SummFreq += 4;
672
+  if (s[0].Freq > s[-1].Freq)
673
+  {
674
+    SwapStates(&s[0], &s[-1]);
675
+    p->FoundState = --s;
676
+    if (s->Freq > MAX_FREQ)
677
+      Rescale(p);
678
+  }
679
+  NextContext(p);
680
+}
681
+
682
+void Ppmd7_Update1_0(CPpmd7 *p)
683
+{
684
+  p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq);
685
+  p->RunLength += p->PrevSuccess;
686
+  p->MinContext->SummFreq += 4;
687
+  if ((p->FoundState->Freq += 4) > MAX_FREQ)
688
+    Rescale(p);
689
+  NextContext(p);
690
+}
691
+
692
+void Ppmd7_UpdateBin(CPpmd7 *p)
693
+{
694
+  p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0));
695
+  p->PrevSuccess = 1;
696
+  p->RunLength++;
697
+  NextContext(p);
698
+}
699
+
700
+void Ppmd7_Update2(CPpmd7 *p)
701
+{
702
+  p->MinContext->SummFreq += 4;
703
+  if ((p->FoundState->Freq += 4) > MAX_FREQ)
704
+    Rescale(p);
705
+  p->RunLength = p->InitRL;
706
+  UpdateModel(p);
707
+}
0 708
new file mode 100644
... ...
@@ -0,0 +1,140 @@
0
+/* Ppmd7.h -- PPMdH compression codec
1
+2010-03-12 : Igor Pavlov : Public domain
2
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
3
+
4
+/* This code supports virtual RangeDecoder and includes the implementation
5
+of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
6
+If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
7
+
8
+#ifndef __PPMD7_H
9
+#define __PPMD7_H
10
+
11
+#include "Ppmd.h"
12
+
13
+EXTERN_C_BEGIN
14
+
15
+#define PPMD7_MIN_ORDER 2
16
+#define PPMD7_MAX_ORDER 64
17
+
18
+#define PPMD7_MIN_MEM_SIZE (1 << 11)
19
+#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
20
+
21
+struct CPpmd7_Context_;
22
+
23
+typedef
24
+  #ifdef PPMD_32BIT
25
+    struct CPpmd7_Context_ *
26
+  #else
27
+    UInt32
28
+  #endif
29
+  CPpmd7_Context_Ref;
30
+
31
+typedef struct CPpmd7_Context_
32
+{
33
+  UInt16 NumStats;
34
+  UInt16 SummFreq;
35
+  CPpmd_State_Ref Stats;
36
+  CPpmd7_Context_Ref Suffix;
37
+} CPpmd7_Context;
38
+
39
+#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
40
+
41
+typedef struct
42
+{
43
+  CPpmd7_Context *MinContext, *MaxContext;
44
+  CPpmd_State *FoundState;
45
+  unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
46
+  Int32 RunLength, InitRL; /* must be 32-bit at least */
47
+
48
+  UInt32 Size;
49
+  UInt32 GlueCount;
50
+  Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
51
+  UInt32 AlignOffset;
52
+
53
+  Byte Indx2Units[PPMD_NUM_INDEXES];
54
+  Byte Units2Indx[128];
55
+  CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
56
+  Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
57
+  CPpmd_See DummySee, See[25][16];
58
+  UInt16 BinSumm[128][64];
59
+} CPpmd7;
60
+
61
+void Ppmd7_Construct(CPpmd7 *p);
62
+Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
63
+void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc);
64
+void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);
65
+#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
66
+
67
+
68
+/* ---------- Internal Functions ---------- */
69
+
70
+extern const Byte PPMD7_kExpEscape[16];
71
+
72
+#ifdef PPMD_32BIT
73
+  #define Ppmd7_GetPtr(p, ptr) (ptr)
74
+  #define Ppmd7_GetContext(p, ptr) (ptr)
75
+  #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats)
76
+#else
77
+  #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
78
+  #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs)))
79
+  #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats)))
80
+#endif
81
+
82
+void Ppmd7_Update1(CPpmd7 *p);
83
+void Ppmd7_Update1_0(CPpmd7 *p);
84
+void Ppmd7_Update2(CPpmd7 *p);
85
+void Ppmd7_UpdateBin(CPpmd7 *p);
86
+
87
+#define Ppmd7_GetBinSumm(p) \
88
+    &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \
89
+    p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \
90
+    (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \
91
+    2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \
92
+    ((p->RunLength >> 26) & 0x20)]
93
+
94
+CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);
95
+
96
+
97
+/* ---------- Decode ---------- */
98
+
99
+typedef struct
100
+{
101
+  UInt32 (*GetThreshold)(void *p, UInt32 total);
102
+  void (*Decode)(void *p, UInt32 start, UInt32 size);
103
+  UInt32 (*DecodeBit)(void *p, UInt32 size0);
104
+} IPpmd7_RangeDec;
105
+
106
+typedef struct
107
+{
108
+  IPpmd7_RangeDec p;
109
+  UInt32 Range;
110
+  UInt32 Code;
111
+  IByteIn *Stream;
112
+} CPpmd7z_RangeDec;
113
+
114
+void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p);
115
+Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p);
116
+#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
117
+
118
+int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc);
119
+
120
+
121
+/* ---------- Encode ---------- */
122
+
123
+typedef struct
124
+{
125
+  UInt64 Low;
126
+  UInt32 Range;
127
+  Byte Cache;
128
+  UInt64 CacheSize;
129
+  IByteOut *Stream;
130
+} CPpmd7z_RangeEnc;
131
+
132
+void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p);
133
+void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p);
134
+
135
+void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
136
+
137
+EXTERN_C_END
138
+ 
139
+#endif
0 140
new file mode 100644
... ...
@@ -0,0 +1,187 @@
0
+/* Ppmd7Dec.c -- PPMdH Decoder
1
+2010-03-12 : Igor Pavlov : Public domain
2
+This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
3
+
4
+#include "Ppmd7.h"
5
+
6
+#define kTopValue (1 << 24)
7
+
8
+Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p)
9
+{
10
+  unsigned i;
11
+  p->Code = 0;
12
+  p->Range = 0xFFFFFFFF;
13
+  if (p->Stream->Read((void *)p->Stream) != 0)
14
+    return False;
15
+  for (i = 0; i < 4; i++)
16
+    p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
17
+  return (p->Code < 0xFFFFFFFF);
18
+}
19
+
20
+static UInt32 Range_GetThreshold(void *pp, UInt32 total)
21
+{
22
+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
23
+  return (p->Code) / (p->Range /= total);
24
+}
25
+
26
+static void Range_Normalize(CPpmd7z_RangeDec *p)
27
+{
28
+  if (p->Range < kTopValue)
29
+  {
30
+    p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
31
+    p->Range <<= 8;
32
+    if (p->Range < kTopValue)
33
+    {
34
+      p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream);
35
+      p->Range <<= 8;
36
+    }
37
+  }
38
+}
39
+
40
+static void Range_Decode(void *pp, UInt32 start, UInt32 size)
41
+{
42
+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
43
+  p->Code -= start * p->Range;
44
+  p->Range *= size;
45
+  Range_Normalize(p);
46
+}
47
+
48
+static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
49
+{
50
+  CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp;
51
+  UInt32 newBound = (p->Range >> 14) * size0;
52
+  UInt32 symbol;
53
+  if (p->Code < newBound)
54
+  {
55
+    symbol = 0;
56
+    p->Range = newBound;
57
+  }
58
+  else
59
+  {
60
+    symbol = 1;
61
+    p->Code -= newBound;
62
+    p->Range -= newBound;
63
+  }
64
+  Range_Normalize(p);
65
+  return symbol;
66
+}
67
+
68
+void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p)
69
+{
70
+  p->p.GetThreshold = Range_GetThreshold;
71
+  p->p.Decode = Range_Decode;
72
+  p->p.DecodeBit = Range_DecodeBit;
73
+}
74
+
75
+
76
+#define MASK(sym) ((signed char *)charMask)[sym]
77
+
78
+int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc)
79
+{
80
+  size_t charMask[256 / sizeof(size_t)];
81
+  if (p->MinContext->NumStats != 1)
82
+  {
83
+    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);
84
+    unsigned i;
85
+    UInt32 count, hiCnt;
86
+    if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq))
87
+    {
88
+      Byte symbol;
89
+      rc->Decode(rc, 0, s->Freq);
90
+      p->FoundState = s;
91
+      symbol = s->Symbol;
92
+      Ppmd7_Update1_0(p);
93
+      return symbol;
94
+    }
95
+    p->PrevSuccess = 0;
96
+    i = p->MinContext->NumStats - 1;
97
+    do
98
+    {
99
+      if ((hiCnt += (++s)->Freq) > count)
100
+      {
101
+        Byte symbol;
102
+        rc->Decode(rc, hiCnt - s->Freq, s->Freq);
103
+        p->FoundState = s;
104
+        symbol = s->Symbol;
105
+        Ppmd7_Update1(p);
106
+        return symbol;
107
+      }
108
+    }
109
+    while (--i);
110
+    if (count >= p->MinContext->SummFreq)
111
+      return -2;
112
+    p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol];
113
+    rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt);
114
+    PPMD_SetAllBitsIn256Bytes(charMask);
115
+    MASK(s->Symbol) = 0;
116
+    i = p->MinContext->NumStats - 1;
117
+    do { MASK((--s)->Symbol) = 0; } while (--i);
118
+  }
119
+  else
120
+  {
121
+    UInt16 *prob = Ppmd7_GetBinSumm(p);
122
+    if (rc->DecodeBit(rc, *prob) == 0)
123
+    {
124
+      Byte symbol;
125
+      *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob);
126
+      symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;
127
+      Ppmd7_UpdateBin(p);
128
+      return symbol;
129
+    }
130
+    *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob);
131
+    p->InitEsc = PPMD7_kExpEscape[*prob >> 10];
132
+    PPMD_SetAllBitsIn256Bytes(charMask);
133
+    MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;
134
+    p->PrevSuccess = 0;
135
+  }
136
+  for (;;)
137
+  {
138
+    CPpmd_State *ps[256], *s;
139
+    UInt32 freqSum, count, hiCnt;
140
+    CPpmd_See *see;
141
+    unsigned i, num, numMasked = p->MinContext->NumStats;
142
+    do
143
+    {
144
+      p->OrderFall++;
145
+      if (!p->MinContext->Suffix)
146
+        return -1;
147
+      p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix);
148
+    }
149
+    while (p->MinContext->NumStats == numMasked);
150
+    hiCnt = 0;
151
+    s = Ppmd7_GetStats(p, p->MinContext);
152
+    i = 0;
153
+    num = p->MinContext->NumStats - numMasked;
154
+    do
155
+    {
156
+      int k = (int)(MASK(s->Symbol));
157
+      hiCnt += (s->Freq & k);
158
+      ps[i] = s++;
159
+      i -= k;
160
+    }
161
+    while (i != num);
162
+    
163
+    see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);
164
+    freqSum += hiCnt;
165
+    count = rc->GetThreshold(rc, freqSum);
166
+    
167
+    if (count < hiCnt)
168
+    {
169
+      Byte symbol;
170
+      CPpmd_State **pps = ps;
171
+      for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++);
172
+      s = *pps;
173
+      rc->Decode(rc, hiCnt - s->Freq, s->Freq);
174
+      Ppmd_See_Update(see);
175
+      p->FoundState = s;
176
+      symbol = s->Symbol;
177
+      Ppmd7_Update2(p);
178
+      return symbol;
179
+    }
180
+    if (count >= freqSum)
181
+      return -2;
182
+    rc->Decode(rc, hiCnt, freqSum - hiCnt);
183
+    see->Summ = (UInt16)(see->Summ + freqSum);
184
+    do { MASK(ps[--i]->Symbol) = 0; } while (i != 0);
185
+  }
186
+}
... ...
@@ -1,5 +1,5 @@
1 1
 /* Types.h -- Basic types
2
-2008-11-23 : Igor Pavlov : Public domain */
2
+2010-10-09 : Igor Pavlov : Public domain */
3 3
 
4 4
 #ifndef __7Z_TYPES_H
5 5
 #define __7Z_TYPES_H
... ...
@@ -10,9 +10,18 @@
10 10
 #include <windows.h>
11 11
 #endif
12 12
 
13
-/* aCaB -- lame workaround for "Byte" refef */
14
-#include <zconf.h>
13
+#ifndef EXTERN_C_BEGIN
14
+#ifdef __cplusplus
15
+#define EXTERN_C_BEGIN extern "C" {
16
+#define EXTERN_C_END }
17
+#else
18
+#define EXTERN_C_BEGIN
19
+#define EXTERN_C_END
20
+#endif
21
+#endif
15 22
 
23
+EXTERN_C_BEGIN
24
+#include "fmap.h"
16 25
 #define SZ_OK 0
17 26
 
18 27
 #define SZ_ERROR_DATA 1
... ...
@@ -31,6 +40,9 @@
31 31
 #define SZ_ERROR_ARCHIVE 16
32 32
 #define SZ_ERROR_NO_ARCHIVE 17
33 33
 
34
+/* ACAB */
35
+#define SZ_ERROR_ENCRYPTED 18
36
+
34 37
 typedef int SRes;
35 38
 
36 39
 #ifdef _WIN32
... ...
@@ -43,9 +55,7 @@ typedef int WRes;
43 43
 #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
44 44
 #endif
45 45
 
46
-/* aCaB -- use Byte defined in zconf.h
47 46
 typedef unsigned char Byte;
48
-*/
49 47
 typedef short Int16;
50 48
 typedef unsigned short UInt16;
51 49
 
... ...
@@ -70,9 +80,11 @@ typedef unsigned long UInt64;
70 70
 #if defined(_MSC_VER) || defined(__BORLANDC__)
71 71
 typedef __int64 Int64;
72 72
 typedef unsigned __int64 UInt64;
73
+#define UINT64_CONST(n) n
73 74
 #else
74 75
 typedef long long int Int64;
75 76
 typedef unsigned long long int UInt64;
77
+#define UINT64_CONST(n) n ## ULL
76 78
 #endif
77 79
 
78 80
 #endif
... ...
@@ -88,6 +100,12 @@ typedef int Bool;
88 88
 #define False 0
89 89
 
90 90
 
91
+#ifdef _WIN32
92
+#define MY_STD_CALL __stdcall
93
+#else
94
+#define MY_STD_CALL
95
+#endif
96
+
91 97
 #ifdef _MSC_VER
92 98
 
93 99
 #if _MSC_VER >= 1300
... ...
@@ -97,13 +115,11 @@ typedef int Bool;
97 97
 #endif
98 98
 
99 99
 #define MY_CDECL __cdecl
100
-#define MY_STD_CALL __stdcall
101
-#define MY_FAST_CALL MY_NO_INLINE __fastcall
100
+#define MY_FAST_CALL __fastcall
102 101
 
103 102
 #else
104 103
 
105 104
 #define MY_CDECL
106
-#define MY_STD_CALL
107 105
 #define MY_FAST_CALL
108 106
 
109 107
 #endif
... ...
@@ -113,6 +129,16 @@ typedef int Bool;
113 113
 
114 114
 typedef struct
115 115
 {
116
+  Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
117
+} IByteIn;
118
+
119
+typedef struct
120
+{
121
+  void (*Write)(void *p, Byte b);
122
+} IByteOut;
123
+
124
+typedef struct
125
+{
116 126
   SRes (*Read)(void *p, void *buf, size_t *size);
117 127
     /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
118 128
        (output(*size) < input(*size)) is allowed */
... ...
@@ -141,11 +167,12 @@ typedef struct
141 141
 {
142 142
   SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */
143 143
   SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
144
+    off_t curpos;
144 145
 } ISeekInStream;
145 146
 
146 147
 typedef struct
147 148
 {
148
-  SRes (*Look)(void *p, void **buf, size_t *size);
149
+  SRes (*Look)(void *p, const void **buf, size_t *size);
149 150
     /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
150 151
        (output(*size) > input(*size)) is not allowed
151 152
        (output(*size) < input(*size)) is allowed */
... ...
@@ -210,4 +237,22 @@ typedef struct
210 210
 #define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
211 211
 #define IAlloc_Free(p, a) (p)->Free((p), a)
212 212
 
213
+#ifdef _WIN32
214
+
215
+#define CHAR_PATH_SEPARATOR '\\'
216
+#define WCHAR_PATH_SEPARATOR L'\\'
217
+#define STRING_PATH_SEPARATOR "\\"
218
+#define WSTRING_PATH_SEPARATOR L"\\"
219
+
220
+#else
221
+
222
+#define CHAR_PATH_SEPARATOR '/'
223
+#define WCHAR_PATH_SEPARATOR L'/'
224
+#define STRING_PATH_SEPARATOR "/"
225
+#define WSTRING_PATH_SEPARATOR L"/"
226
+
227
+#endif
228
+
229
+EXTERN_C_END
230
+
213 231
 #endif
214 232
new file mode 100644
... ...
@@ -0,0 +1,295 @@
0
+diff -wu lzma_orig//7zCrc.c 7z/7zCrc.c
1
+--- lzma_orig//7zCrc.c	2011-06-18 01:48:31.343602685 +0200
2
+@@ -4,24 +4,12 @@
3
+ #include "7zCrc.h"
4
+ #include "CpuArch.h"
5
+ 
6
+-#define kCrcPoly 0xEDB88320
7
++const UInt32 g_CrcTable[256] = { 0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
8
+ 
9
+-#ifdef MY_CPU_LE
10
+-#define CRC_NUM_TABLES 8
11
+-#else
12
+-#define CRC_NUM_TABLES 1
13
+-#endif
14
+ 
15
+-typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
16
++#define CRC_UPDATE_BYTE_2(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
17
+ 
18
+-static CRC_FUNC g_CrcUpdate;
19
+-UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
20
+-
21
+-#if CRC_NUM_TABLES == 1
22
+-
23
+-#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
24
+-
25
+-static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
26
++UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
27
+ {
28
+   const Byte *p = (const Byte *)data;
29
+   for (; size > 0; size--, p++)
30
+@@ -29,46 +17,7 @@
31
+   return v;
32
+ }
33
+ 
34
+-#else
35
+-
36
+-UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
37
+-UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
38
+-
39
+-#endif
40
+-
41
+-UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
42
+-{
43
+-  return g_CrcUpdate(v, data, size, g_CrcTable);
44
+-}
45
+-
46
+ UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
47
+ {
48
+-  return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
49
+-}
50
+-
51
+-void MY_FAST_CALL CrcGenerateTable()
52
+-{
53
+-  UInt32 i;
54
+-  for (i = 0; i < 256; i++)
55
+-  {
56
+-    UInt32 r = i;
57
+-    unsigned j;
58
+-    for (j = 0; j < 8; j++)
59
+-      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
60
+-    g_CrcTable[i] = r;
61
+-  }
62
+-  #if CRC_NUM_TABLES == 1
63
+-  g_CrcUpdate = CrcUpdateT1;
64
+-  #else
65
+-  for (; i < 256 * CRC_NUM_TABLES; i++)
66
+-  {
67
+-    UInt32 r = g_CrcTable[i - 256];
68
+-    g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
69
+-  }
70
+-  g_CrcUpdate = CrcUpdateT4;
71
+-  #ifdef MY_CPU_X86_OR_AMD64
72
+-  if (!CPU_Is_InOrder())
73
+-    g_CrcUpdate = CrcUpdateT8;
74
+-  #endif
75
+-  #endif
76
++  return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;
77
+ }
78
+diff -wu lzma_orig//7zCrc.h 7z/7zCrc.h
79
+--- lzma_orig//7zCrc.h	2011-06-18 01:48:31.343602685 +0200
80
+@@ -8,14 +8,7 @@
81
+ 
82
+ EXTERN_C_BEGIN
83
+ 
84
+-extern UInt32 g_CrcTable[];
85
+-
86
+-/* Call CrcGenerateTable one time before other CRC functions */
87
+-void MY_FAST_CALL CrcGenerateTable(void);
88
+-
89
+ #define CRC_INIT_VAL 0xFFFFFFFF
90
+-#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
91
+-#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
92
+ 
93
+ UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
94
+ UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
95
+diff -wu lzma_orig//7zDec.c 7z/7zDec.c
96
+--- lzma_orig//7zDec.c	2011-06-18 01:48:31.347602680 +0200
97
+@@ -3,7 +3,7 @@
98
+ 
99
+ #include <string.h>
100
+ 
101
+-/* #define _7ZIP_PPMD_SUPPPORT */
102
++#define _7ZIP_PPMD_SUPPPORT
103
+ 
104
+ #include "7z.h"
105
+ 
106
+diff -wu lzma_orig//7zFile.h 7z/7zFile.h
107
+--- lzma_orig//7zFile.h	2011-06-18 01:48:31.347602680 +0200
108
+@@ -27,6 +27,7 @@
109
+   #else
110
+   FILE *file;
111
+   #endif
112
++    fmap_t *fmap;
113
+ } CSzFile;
114
+ 
115
+ void File_Construct(CSzFile *p);
116
+diff -wu lzma_orig//CpuArch.h 7z/CpuArch.h
117
+--- lzma_orig//CpuArch.h	2011-06-18 01:48:31.363602662 +0200
118
+@@ -5,6 +5,7 @@
119
+ #define __CPU_ARCH_H
120
+ 
121
+ #include "Types.h"
122
++#include "others.h"
123
+ 
124
+ EXTERN_C_BEGIN
125
+ 
126
+@@ -16,68 +17,8 @@
127
+ If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
128
+ */
129
+ 
130
+-#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
131
+-#define MY_CPU_AMD64
132
+-#endif
133
+-
134
+-#if defined(MY_CPU_AMD64) || defined(_M_IA64)
135
+-#define MY_CPU_64BIT
136
+-#endif
137
+-
138
+-#if defined(_M_IX86) || defined(__i386__)
139
+-#define MY_CPU_X86
140
+-#endif
141
+-
142
+-#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
143
+-#define MY_CPU_X86_OR_AMD64
144
+-#endif
145
+-
146
+-#if defined(MY_CPU_X86) || defined(_M_ARM)
147
+-#define MY_CPU_32BIT
148
+-#endif
149
+-
150
+-#if defined(_WIN32) && defined(_M_ARM)
151
+-#define MY_CPU_ARM_LE
152
+-#endif
153
+-
154
+-#if defined(_WIN32) && defined(_M_IA64)
155
+-#define MY_CPU_IA64_LE
156
+-#endif
157
+-
158
+-#if defined(MY_CPU_X86_OR_AMD64)
159
+-#define MY_CPU_LE_UNALIGN
160
+-#endif
161
+-
162
+-#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE)  || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
163
+-#define MY_CPU_LE
164
+-#endif
165
+-
166
+-#if defined(__BIG_ENDIAN__)
167
+-#define MY_CPU_BE
168
+-#endif
169
+-
170
+-#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
171
+-Stop_Compiling_Bad_Endian
172
+-#endif
173
+-
174
+-#ifdef MY_CPU_LE_UNALIGN
175
+-
176
+-#define GetUi16(p) (*(const UInt16 *)(p))
177
+-#define GetUi32(p) (*(const UInt32 *)(p))
178
+-#define GetUi64(p) (*(const UInt64 *)(p))
179
+-#define SetUi16(p, d) *(UInt16 *)(p) = (d);
180
+-#define SetUi32(p, d) *(UInt32 *)(p) = (d);
181
+-#define SetUi64(p, d) *(UInt64 *)(p) = (d);
182
+-
183
+-#else
184
+-
185
+-#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
186
+-
187
+-#define GetUi32(p) ( \
188
+-             ((const Byte *)(p))[0]        | \
189
+-    ((UInt32)((const Byte *)(p))[1] <<  8) | \
190
+-    ((UInt32)((const Byte *)(p))[2] << 16) | \
191
+-    ((UInt32)((const Byte *)(p))[3] << 24))
192
++#define GetUi16(p) (cli_readint16(p))
193
++#define GetUi32(p) (cli_readint32(p))
194
+ 
195
+ #define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
196
+ 
197
+@@ -85,71 +26,12 @@
198
+     ((Byte *)(p))[0] = (Byte)_x_; \
199
+     ((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
200
+ 
201
+-#define SetUi32(p, d) { UInt32 _x_ = (d); \
202
+-    ((Byte *)(p))[0] = (Byte)_x_; \
203
+-    ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
204
+-    ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
205
+-    ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
206
++#define SetUi32(p, d) (cli_writeint32(p, d))
207
+ 
208
+ #define SetUi64(p, d) { UInt64 _x64_ = (d); \
209
+     SetUi32(p, (UInt32)_x64_); \
210
+     SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
211
+ 
212
+-#endif
213
+-
214
+-#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
215
+-
216
+-#pragma intrinsic(_byteswap_ulong)
217
+-#pragma intrinsic(_byteswap_uint64)
218
+-#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
219
+-#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
220
+-
221
+-#else
222
+-
223
+-#define GetBe32(p) ( \
224
+-    ((UInt32)((const Byte *)(p))[0] << 24) | \
225
+-    ((UInt32)((const Byte *)(p))[1] << 16) | \
226
+-    ((UInt32)((const Byte *)(p))[2] <<  8) | \
227
+-             ((const Byte *)(p))[3] )
228
+-
229
+-#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
230
+-
231
+-#endif
232
+-
233
+-#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
234
+-
235
+-
236
+-#ifdef MY_CPU_X86_OR_AMD64
237
+-
238
+-typedef struct
239
+-{
240
+-  UInt32 maxFunc;
241
+-  UInt32 vendor[3];
242
+-  UInt32 ver;
243
+-  UInt32 b;
244
+-  UInt32 c;
245
+-  UInt32 d;
246
+-} Cx86cpuid;
247
+-
248
+-enum
249
+-{
250
+-  CPU_FIRM_INTEL,
251
+-  CPU_FIRM_AMD,
252
+-  CPU_FIRM_VIA
253
+-};
254
+-
255
+-Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
256
+-int x86cpuid_GetFirm(const Cx86cpuid *p);
257
+-
258
+-#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
259
+-#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
260
+-#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
261
+-
262
+-Bool CPU_Is_InOrder();
263
+-Bool CPU_Is_Aes_Supported();
264
+-
265
+-#endif
266
+-
267
+ EXTERN_C_END
268
+ 
269
+ #endif
270
+diff -wu lzma_orig//Types.h 7z/Types.h
271
+--- lzma_orig//Types.h	2011-06-18 01:48:31.379602643 +0200
272
+@@ -21,7 +21,7 @@
273
+ #endif
274
+ 
275
+ EXTERN_C_BEGIN
276
+-
277
++#include "fmap.h"
278
+ #define SZ_OK 0
279
+ 
280
+ #define SZ_ERROR_DATA 1
281
+@@ -164,6 +164,7 @@
282
+ {
283
+   SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */
284
+   SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
285
++    off_t curpos;
286
+ } ISeekInStream;
287
+ 
288
+ typedef struct
0 289
deleted file mode 100644
... ...
@@ -1,594 +0,0 @@
1
-LZMA SDK 4.65
2
-
3
-LZMA SDK provides the documentation, samples, header files, libraries, 
4
-and tools you need to develop applications that use LZMA compression.
5
-
6
-LZMA is default and general compression method of 7z format
7
-in 7-Zip compression program (www.7-zip.org). LZMA provides high 
8
-compression ratio and very fast decompression.
9
-
10
-LZMA is an improved version of famous LZ77 compression algorithm. 
11
-It was improved in way of maximum increasing of compression ratio,
12
-keeping high decompression speed and low memory requirements for 
13
-decompressing.
14
-
15
-
16
-
17
-LICENSE
18
-
19
-LZMA SDK is written and placed in the public domain by Igor Pavlov.
20
-
21
-
22
-LZMA SDK Contents
23
-
24
-LZMA SDK includes:
25
-
26
-  - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing
27
-  - Compiled file->file LZMA compressing/decompressing program for Windows system
28
-
29
-
30
-UNIX/Linux version 
31
-To compile C++ version of file->file LZMA encoding, go to directory
32
-C++/7zip/Compress/LZMA_Alone 
33
-and call make to recompile it:
34
-  make -f makefile.gcc clean all
35
-
36
-In some UNIX/Linux versions you must compile LZMA with static libraries.
37
-To compile with static libraries, you can use 
38
-LIB = -lm -static
39
-
40
-
41
-Files
42
-lzma.txt     - LZMA SDK description (this file)
43
-7zFormat.txt - 7z Format description
44
-7zC.txt      - 7z ANSI-C Decoder description
45
-methods.txt  - Compression method IDs for .7z
46
-lzma.exe     - Compiled file->file LZMA encoder/decoder for Windows
47
-history.txt  - history of the LZMA SDK
48
-
49
-
50
-Source code structure
51
-
52
-C/  - C files
53
-        7zCrc*.*   - CRC code
54
-        Alloc.*    - Memory allocation functions
55
-        Bra*.*     - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
56
-        LzFind.*   - Match finder for LZ (LZMA) encoders 
57
-        LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding
58
-        LzHash.h   - Additional file for LZ match finder
59
-        LzmaDec.*  - LZMA decoding
60
-        LzmaEnc.*  - LZMA encoding
61
-        LzmaLib.*  - LZMA Library for DLL calling
62
-        Types.h    - Basic types for another .c files
63
-	Threads.*  - The code for multithreading.
64
-
65
-    LzmaLib  - LZMA Library (.DLL for Windows)
66
-    
67
-    LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).
68
-
69
-    Archive - files related to archiving
70
-      7z     - 7z ANSI-C Decoder
71
-
72
-CPP/ -- CPP files
73
-
74
-  Common  - common files for C++ projects
75
-  Windows - common files for Windows related code
76
-
77
-  7zip    - files related to 7-Zip Project
78
-
79
-    Common   - common files for 7-Zip
80
-
81
-    Compress - files related to compression/decompression
82
-
83
-      Copy         - Copy coder
84
-      RangeCoder   - Range Coder (special code of compression/decompression)
85
-      LZMA         - LZMA compression/decompression on C++
86
-      LZMA_Alone   - file->file LZMA compression/decompression
87
-      Branch       - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
88
-
89
-    Archive - files related to archiving
90
-
91
-      Common   - common files for archive handling
92
-      7z       - 7z C++ Encoder/Decoder
93
-
94
-    Bundles    - Modules that are bundles of other modules
95
-  
96
-      Alone7z           - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
97
-      Format7zR         - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
98
-      Format7zExtractR  - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
99
-
100
-    UI        - User Interface files
101
-         
102
-      Client7z - Test application for 7za.dll,  7zr.dll, 7zxr.dll
103
-      Common   - Common UI files
104
-      Console  - Code for console archiver
105
-
106
-
107
-
108
-CS/ - C# files
109
-  7zip
110
-    Common   - some common files for 7-Zip
111
-    Compress - files related to compression/decompression
112
-      LZ     - files related to LZ (Lempel-Ziv) compression algorithm
113
-      LZMA         - LZMA compression/decompression
114
-      LzmaAlone    - file->file LZMA compression/decompression
115
-      RangeCoder   - Range Coder (special code of compression/decompression)
116
-
117
-Java/  - Java files
118
-  SevenZip
119
-    Compression    - files related to compression/decompression
120
-      LZ           - files related to LZ (Lempel-Ziv) compression algorithm
121
-      LZMA         - LZMA compression/decompression
122
-      RangeCoder   - Range Coder (special code of compression/decompression)
123
-
124
-
125
-C/C++ source code of LZMA SDK is part of 7-Zip project.
126
-7-Zip source code can be downloaded from 7-Zip's SourceForge page:
127
-
128
-  http://sourceforge.net/projects/sevenzip/
129
-
130
-
131
-
132
-LZMA features
133
-  - Variable dictionary size (up to 1 GB)
134
-  - Estimated compressing speed: about 2 MB/s on 2 GHz CPU
135
-  - Estimated decompressing speed: 
136
-      - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64
137
-      - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC
138
-  - Small memory requirements for decompressing (16 KB + DictionarySize)
139
-  - Small code size for decompressing: 5-8 KB
140
-
141
-LZMA decoder uses only integer operations and can be 
142
-implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).
143
-
144
-Some critical operations that affect the speed of LZMA decompression:
145
-  1) 32*16 bit integer multiply
146
-  2) Misspredicted branches (penalty mostly depends from pipeline length)
147
-  3) 32-bit shift and arithmetic operations
148
-
149
-The speed of LZMA decompressing mostly depends from CPU speed.
150
-Memory speed has no big meaning. But if your CPU has small data cache, 
151
-overall weight of memory speed will slightly increase.
152
-
153
-
154
-How To Use
155
-
156
-Using LZMA encoder/decoder executable
157
-
158
-Usage:  LZMA <e|d> inputFile outputFile [<switches>...]
159
-
160
-  e: encode file
161
-
162
-  d: decode file
163
-
164
-  b: Benchmark. There are two tests: compressing and decompressing 
165
-     with LZMA method. Benchmark shows rating in MIPS (million 
166
-     instructions per second). Rating value is calculated from 
167
-     measured speed and it is normalized with Intel's Core 2 results.
168
-     Also Benchmark checks possible hardware errors (RAM 
169
-     errors in most cases). Benchmark uses these settings:
170
-     (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. 
171
-     Also you can change the number of iterations. Example for 30 iterations:
172
-       LZMA b 30
173
-     Default number of iterations is 10.
174
-
175
-<Switches>
176
-  
177
-
178
-  -a{N}:  set compression mode 0 = fast, 1 = normal
179
-          default: 1 (normal)
180
-
181
-  d{N}:   Sets Dictionary size - [0, 30], default: 23 (8MB)
182
-          The maximum value for dictionary size is 1 GB = 2^30 bytes.
183
-          Dictionary size is calculated as DictionarySize = 2^N bytes. 
184
-          For decompressing file compressed by LZMA method with dictionary 
185
-          size D = 2^N you need about D bytes of memory (RAM).
186
-
187
-  -fb{N}: set number of fast bytes - [5, 273], default: 128
188
-          Usually big number gives a little bit better compression ratio 
189
-          and slower compression process.
190
-
191
-  -lc{N}: set number of literal context bits - [0, 8], default: 3
192
-          Sometimes lc=4 gives gain for big files.
193
-
194
-  -lp{N}: set number of literal pos bits - [0, 4], default: 0
195
-          lp switch is intended for periodical data when period is 
196
-          equal 2^N. For example, for 32-bit (4 bytes) 
197
-          periodical data you can use lp=2. Often it's better to set lc0, 
198
-          if you change lp switch.
199
-
200
-  -pb{N}: set number of pos bits - [0, 4], default: 2
201
-          pb switch is intended for periodical data 
202
-          when period is equal 2^N.
203
-
204
-  -mf{MF_ID}: set Match Finder. Default: bt4. 
205
-              Algorithms from hc* group doesn't provide good compression 
206
-              ratio, but they often works pretty fast in combination with 
207
-              fast mode (-a0).
208
-
209
-              Memory requirements depend from dictionary size 
210
-              (parameter "d" in table below). 
211
-
212
-               MF_ID     Memory                   Description
213
-
214
-                bt2    d *  9.5 + 4MB  Binary Tree with 2 bytes hashing.
215
-                bt3    d * 11.5 + 4MB  Binary Tree with 3 bytes hashing.
216
-                bt4    d * 11.5 + 4MB  Binary Tree with 4 bytes hashing.
217
-                hc4    d *  7.5 + 4MB  Hash Chain with 4 bytes hashing.
218
-
219
-  -eos:   write End Of Stream marker. By default LZMA doesn't write 
220
-          eos marker, since LZMA decoder knows uncompressed size 
221
-          stored in .lzma file header.
222
-
223
-  -si:    Read data from stdin (it will write End Of Stream marker).
224
-  -so:    Write data to stdout
225
-
226
-
227
-Examples:
228
-
229
-1) LZMA e file.bin file.lzma -d16 -lc0 
230
-
231
-compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)  
232
-and 0 literal context bits. -lc0 allows to reduce memory requirements 
233
-for decompression.
234
-
235
-
236
-2) LZMA e file.bin file.lzma -lc0 -lp2
237
-
238
-compresses file.bin to file.lzma with settings suitable 
239
-for 32-bit periodical data (for example, ARM or MIPS code).
240
-
241
-3) LZMA d file.lzma file.bin
242
-
243
-decompresses file.lzma to file.bin.
244
-
245
-
246
-Compression ratio hints
247
-
248
-Recommendations
249
-
250
-To increase the compression ratio for LZMA compressing it's desirable 
251
-to have aligned data (if it's possible) and also it's desirable to locate
252
-data in such order, where code is grouped in one place and data is 
253
-grouped in other place (it's better than such mixing: code, data, code,
254
-data, ...).
255
-
256
-
257
-Filters
258
-You can increase the compression ratio for some data types, using
259
-special filters before compressing. For example, it's possible to 
260
-increase the compression ratio on 5-10% for code for those CPU ISAs: 
261
-x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.
262
-
263
-You can find C source code of such filters in C/Bra*.* files
264
-
265
-You can check the compression ratio gain of these filters with such 
266
-7-Zip commands (example for ARM code):
267
-No filter:
268
-  7z a a1.7z a.bin -m0=lzma
269
-
270
-With filter for little-endian ARM code:
271
-  7z a a2.7z a.bin -m0=arm -m1=lzma        
272
-
273
-It works in such manner:
274
-Compressing    = Filter_encoding + LZMA_encoding
275
-Decompressing  = LZMA_decoding + Filter_decoding
276
-
277
-Compressing and decompressing speed of such filters is very high,
278
-so it will not increase decompressing time too much.
279
-Moreover, it reduces decompression time for LZMA_decoding, 
280
-since compression ratio with filtering is higher.
281
-
282
-These filters convert CALL (calling procedure) instructions 
283
-from relative offsets to absolute addresses, so such data becomes more 
284
-compressible.
285
-
286
-For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.
287
-
288
-
289
-LZMA compressed file format
290
-Offset Size Description
291
-  0     1   Special LZMA properties (lc,lp, pb in encoded form)
292
-  1     4   Dictionary size (little endian)
293
-  5     8   Uncompressed size (little endian). -1 means unknown size
294
- 13         Compressed data
295
-
296
-
297
-ANSI-C LZMA Decoder
298
-~~~~~~~~~~~~~~~~~~~
299
-
300
-Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.
301
-If you want to use old interfaces you can download previous version of LZMA SDK
302
-from sourceforge.net site.
303
-
304
-To use ANSI-C LZMA Decoder you need the following files:
305
-1) LzmaDec.h + LzmaDec.c + Types.h
306
-LzmaUtil/LzmaUtil.c is example application that uses these files.
307
-
308
-
309
-Memory requirements for LZMA decoding
310
-
311
-Stack usage of LZMA decoding function for local variables is not 
312
-larger than 200-400 bytes.
313
-
314
-LZMA Decoder uses dictionary buffer and internal state structure.
315
-Internal state structure consumes
316
-  state_size = (4 + (1.5 << (lc + lp))) KB
317
-by default (lc=3, lp=0), state_size = 16 KB.
318
-
319
-
320
-How To decompress data
321
-
322
-LZMA Decoder (ANSI-C version) now supports 2 interfaces:
323
-1) Single-call Decompressing
324
-2) Multi-call State Decompressing (zlib-like interface)
325
-
326
-You must use external allocator:
327
-Example:
328
-void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
329
-void SzFree(void *p, void *address) { p = p; free(address); }
330
-ISzAlloc alloc = { SzAlloc, SzFree };
331
-
332
-You can use p = p; operator to disable compiler warnings.
333
-
334
-
335
-Single-call Decompressing
336
-When to use: RAM->RAM decompressing
337
-Compile files: LzmaDec.h + LzmaDec.c + Types.h
338
-Compile defines: no defines
339
-Memory Requirements:
340
-  - Input buffer: compressed size
341
-  - Output buffer: uncompressed size
342
-  - LZMA Internal Structures: state_size (16 KB for default settings) 
343
-
344
-Interface:
345
-  int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
346
-      const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 
347
-      ELzmaStatus *status, ISzAlloc *alloc);
348
-  In: 
349
-    dest     - output data
350
-    destLen  - output data size
351
-    src      - input data
352
-    srcLen   - input data size
353
-    propData - LZMA properties  (5 bytes)
354
-    propSize - size of propData buffer (5 bytes)
355
-    finishMode - It has meaning only if the decoding reaches output limit (*destLen).
356
-	 LZMA_FINISH_ANY - Decode just destLen bytes.
357
-	 LZMA_FINISH_END - Stream must be finished after (*destLen).
358
-                           You can use LZMA_FINISH_END, when you know that 
359
-                           current output buffer covers last bytes of stream. 
360
-    alloc    - Memory allocator.
361
-
362
-  Out: 
363
-    destLen  - processed output size 
364
-    srcLen   - processed input size 
365
-
366
-  Output:
367
-    SZ_OK
368
-      status:
369
-        LZMA_STATUS_FINISHED_WITH_MARK
370
-        LZMA_STATUS_NOT_FINISHED 
371
-        LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
372
-    SZ_ERROR_DATA - Data error
373
-    SZ_ERROR_MEM  - Memory allocation error
374
-    SZ_ERROR_UNSUPPORTED - Unsupported properties
375
-    SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
376
-
377
-  If LZMA decoder sees end_marker before reaching output limit, it returns OK result,
378
-  and output value of destLen will be less than output buffer size limit.
379
-
380
-  You can use multiple checks to test data integrity after full decompression:
381
-    1) Check Result and "status" variable.
382
-    2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
383
-    3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 
384
-       You must use correct finish mode in that case. */ 
385
-
386
-
387
-Multi-call State Decompressing (zlib-like interface)
388
-
389
-When to use: file->file decompressing 
390
-Compile files: LzmaDec.h + LzmaDec.c + Types.h
391
-
392
-Memory Requirements:
393
- - Buffer for input stream: any size (for example, 16 KB)
394
- - Buffer for output stream: any size (for example, 16 KB)
395
- - LZMA Internal Structures: state_size (16 KB for default settings) 
396
- - LZMA dictionary (dictionary size is encoded in LZMA properties header)
397
-
398
-1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:
399
-   unsigned char header[LZMA_PROPS_SIZE + 8];
400
-   ReadFile(inFile, header, sizeof(header)
401
-
402
-2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties
403
-
404
-  CLzmaDec state;
405
-  LzmaDec_Constr(&state);
406
-  res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
407
-  if (res != SZ_OK)
408
-    return res;
409
-
410
-3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop
411
-
412
-  LzmaDec_Init(&state);
413
-  for (;;)
414
-  {
415
-    ... 
416
-    int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 
417
-    	const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
418
-    ...
419
-  }
420
-
421
-
422
-4) Free all allocated structures
423
-  LzmaDec_Free(&state, &g_Alloc);
424
-
425
-For full code example, look at C/LzmaUtil/LzmaUtil.c code.
426
-
427
-
428
-How To compress data
429
-
430
-Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +
431
-LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h
432
-
433
-Memory Requirements:
434
-  - (dictSize * 11.5 + 6 MB) + state_size
435
-
436
-Lzma Encoder can use two memory allocators:
437
-1) alloc - for small arrays.
438
-2) allocBig - for big arrays.
439
-
440
-For example, you can use Large RAM Pages (2 MB) in allocBig allocator for 
441
-better compression speed. Note that Windows has bad implementation for 
442
-Large RAM Pages. 
443
-It's OK to use same allocator for alloc and allocBig.
444
-
445
-
446
-Single-call Compression with callbacks
447
-
448
-Check C/LzmaUtil/LzmaUtil.c as example, 
449
-
450
-When to use: file->file decompressing 
451
-
452
-1) you must implement callback structures for interfaces:
453
-ISeqInStream
454
-ISeqOutStream
455
-ICompressProgress
456
-ISzAlloc
457
-
458
-static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
459
-static void SzFree(void *p, void *address) {  p = p; MyFree(address); }
460
-static ISzAlloc g_Alloc = { SzAlloc, SzFree };
461
-
462
-  CFileSeqInStream inStream;
463
-  CFileSeqOutStream outStream;
464
-
465
-  inStream.funcTable.Read = MyRead;
466
-  inStream.file = inFile;
467
-  outStream.funcTable.Write = MyWrite;
468
-  outStream.file = outFile;
469
-
470
-
471
-2) Create CLzmaEncHandle object;
472
-
473
-  CLzmaEncHandle enc;
474
-
475
-  enc = LzmaEnc_Create(&g_Alloc);
476
-  if (enc == 0)
477
-    return SZ_ERROR_MEM;
478
-
479
-
480
-3) initialize CLzmaEncProps properties;
481
-
482
-  LzmaEncProps_Init(&props);
483
-
484
-  Then you can change some properties in that structure.
485
-
486
-4) Send LZMA properties to LZMA Encoder
487
-
488
-  res = LzmaEnc_SetProps(enc, &props);
489
-
490
-5) Write encoded properties to header
491
-
492
-    Byte header[LZMA_PROPS_SIZE + 8];
493
-    size_t headerSize = LZMA_PROPS_SIZE;
494
-    UInt64 fileSize;
495
-    int i;
496
-
497
-    res = LzmaEnc_WriteProperties(enc, header, &headerSize);
498
-    fileSize = MyGetFileLength(inFile);
499
-    for (i = 0; i < 8; i++)
500
-      header[headerSize++] = (Byte)(fileSize >> (8 * i));
501
-    MyWriteFileAndCheck(outFile, header, headerSize)
502
-
503
-6) Call encoding function:
504
-      res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, 
505
-        NULL, &g_Alloc, &g_Alloc);
506
-
507
-7) Destroy LZMA Encoder Object
508
-  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
509
-
510
-
511
-If callback function return some error code, LzmaEnc_Encode also returns that code.
512
-
513
-
514
-Single-call RAM->RAM Compression
515
-
516
-Single-call RAM->RAM Compression is similar to Compression with callbacks,
517
-but you provide pointers to buffers instead of pointers to stream callbacks:
518
-
519
-HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
520
-    CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 
521
-    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
522
-
523
-Return code:
524
-  SZ_OK               - OK
525
-  SZ_ERROR_MEM        - Memory allocation error 
526
-  SZ_ERROR_PARAM      - Incorrect paramater
527
-  SZ_ERROR_OUTPUT_EOF - output buffer overflow
528
-  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
529
-
530
-
531
-
532
-LZMA Defines
533
-
534
-_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.
535
-
536
-_LZMA_PROB32   - It can increase the speed on some 32-bit CPUs, but memory usage for 
537
-                 some structures will be doubled in that case.
538
-
539
-_LZMA_UINT32_IS_ULONG  - Define it if int is 16-bit on your compiler and long is 32-bit.
540
-
541
-_LZMA_NO_SYSTEM_SIZE_T  - Define it if you don't want to use size_t type.
542
-
543
-
544
-C++ LZMA Encoder/Decoder 
545
-~~~~~~~~~~~~~~~~~~~~~~~~
546
-C++ LZMA code use COM-like interfaces. So if you want to use it, 
547
-you can study basics of COM/OLE.
548
-C++ LZMA code is just wrapper over ANSI-C code.
549
-
550
-
551
-C++ Notes
552
-~~~~~~~~~~~~~~~~~~~~~~~~
553
-If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),
554
-you must check that you correctly work with "new" operator.
555
-7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.
556
-So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:
557
-operator new(size_t size)
558
-{
559
-  void *p = ::malloc(size);
560
-  if (p == 0)
561
-    throw CNewException();
562
-  return p;
563
-}
564
-If you use MSCV that throws exception for "new" operator, you can compile without 
565
-"NewHandler.cpp". So standard exception will be used. Actually some code of 
566
-7-Zip catches any exception in internal code and converts it to HRESULT code.
567
-So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.
568
-
569
-
570
-http://www.7-zip.org
571
-http://www.7-zip.org/sdk.html
572
-http://www.7-zip.org/support.html
573 1
new file mode 100644
... ...
@@ -0,0 +1,193 @@
0
+/*
1
+ *  Copyright (C) 2011 Sourcefire, Inc.
2
+ *
3
+ *  Authors: aCaB
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+
21
+#include "7z_iface.h"
22
+#include "lzma_iface.h"
23
+#include "scanners.h"
24
+#include "others.h"
25
+#include "fmap.h"
26
+
27
+#include "7z/7z.h"
28
+#include "7z/7zAlloc.h"
29
+#include "7z/7zFile.h"
30
+
31
+
32
+static ISzAlloc allocImp = { __lzma_wrap_alloc, __lzma_wrap_free}, allocTempImp = { __lzma_wrap_alloc, __lzma_wrap_free};
33
+
34
+static SRes FileInStream_fmap_Read(void *pp, void *buf, size_t *size) {
35
+    CFileInStream *p = (CFileInStream *)pp;
36
+    int read_sz;
37
+
38
+    if (*size == 0)
39
+	return 0;
40
+
41
+    read_sz = fmap_readn(p->file.fmap, buf, p->s.curpos, *size);
42
+    if(read_sz < 0)
43
+	return SZ_ERROR_READ;
44
+
45
+    p->s.curpos += read_sz;
46
+
47
+    *size = read_sz;
48
+    return SZ_OK;
49
+}
50
+
51
+static SRes FileInStream_fmap_Seek(void *pp, Int64 *pos, ESzSeek origin) {
52
+    CFileInStream *p = (CFileInStream *)pp;
53
+
54
+    switch (origin) {
55
+    case SZ_SEEK_SET:
56
+	p->s.curpos = *pos;
57
+	break;
58
+    case SZ_SEEK_CUR:
59
+	p->s.curpos += *pos;
60
+	*pos = p->s.curpos;
61
+	break;
62
+    case SZ_SEEK_END:
63
+	p->s.curpos = p->file.fmap->len + *pos;
64
+	*pos = p->s.curpos;
65
+	break;
66
+    default:
67
+	return 1;
68
+    }
69
+    return 0;
70
+}
71
+
72
+#define UTFBUFSZ 256
73
+int cli_7unz (cli_ctx *ctx, size_t offset) {
74
+    CFileInStream archiveStream;
75
+    CLookToRead lookStream;
76
+    CSzArEx db;
77
+    SRes res;
78
+    UInt16 utf16buf[UTFBUFSZ], *utf16name = utf16buf;
79
+    int namelen = UTFBUFSZ, found = CL_CLEAN;
80
+    Int64 begin_of_archive = offset;
81
+
82
+    /* Replacement for 
83
+       FileInStream_CreateVTable(&archiveStream); */
84
+    archiveStream.s.Read = FileInStream_fmap_Read;
85
+    archiveStream.s.Seek = FileInStream_fmap_Seek;
86
+    archiveStream.s.curpos = 0;
87
+    archiveStream.file.fmap = *ctx->fmap;
88
+
89
+    LookToRead_CreateVTable(&lookStream, False);
90
+  
91
+    if(archiveStream.s.Seek(&archiveStream.s, &begin_of_archive, SZ_SEEK_SET) != 0)
92
+	return CL_CLEAN;
93
+
94
+    lookStream.realStream = &archiveStream.s;
95
+    LookToRead_Init(&lookStream);
96
+
97
+    SzArEx_Init(&db);
98
+    res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
99
+    if(res == SZ_OK) {
100
+	UInt32 i, blockIndex = 0xFFFFFFFF;
101
+	Byte *outBuffer = 0;
102
+	size_t outBufferSize = 0;
103
+	unsigned int encrypted = 0;
104
+
105
+	for (i = 0; i < db.db.NumFiles; i++) {
106
+	    size_t offset = 0;
107
+	    size_t outSizeProcessed = 0;
108
+	    const CSzFileItem *f = db.db.Files + i;
109
+	    char *name;
110
+	    size_t j;
111
+	    int newnamelen, fd;
112
+
113
+	    if((found = cli_checklimits("7unz", ctx, 0, 0, 0)))
114
+		break;
115
+
116
+	    if (f->IsDir)
117
+		continue;
118
+
119
+	    if(cli_checklimits("7unz", ctx, f->Size, 0, 0))
120
+		continue;
121
+
122
+	    newnamelen = SzArEx_GetFileNameUtf16(&db, i, NULL);
123
+	    if (newnamelen > namelen) {
124
+		if(namelen > UTFBUFSZ)
125
+		    free(utf16name);
126
+		utf16name = cli_malloc(newnamelen*2);
127
+		if(!utf16name) {
128
+		    found = CL_EMEM;
129
+		    break;
130
+		}
131
+		namelen = newnamelen;
132
+	    }
133
+	    SzArEx_GetFileNameUtf16(&db, i, utf16name);
134
+		
135
+	    name = (char *)utf16name;
136
+	    for(j=0; j<newnamelen; j++) /* FIXME */
137
+		name[j] = utf16name[j];
138
+	    cli_dbgmsg("cli_7unz: extracting %s\n", name);
139
+
140
+	    res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);
141
+	    if(res == SZ_ERROR_ENCRYPTED) {
142
+		encrypted = 1;
143
+		if(DETECT_ENCRYPTED) {
144
+		    cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
145
+		    *ctx->virname = "Heuristics.Encrypted.7Zip";
146
+		    found = CL_VIRUS;
147
+		    break;
148
+		}
149
+	    }
150
+	    if(cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
151
+		found = CL_VIRUS;
152
+		break;
153
+	    }
154
+	    if (res != SZ_OK)
155
+		cli_dbgmsg("cli_unz: extraction failed with %d\n", res);
156
+	    else {
157
+		if((found = cli_gentempfd(NULL, &name, &fd)))
158
+		    break;
159
+		    
160
+		cli_dbgmsg("cli_7unz: Saving to %s\n", name);
161
+		if(cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed)
162
+		    found = CL_EWRITE;
163
+		else
164
+		    found = cli_magic_scandesc(fd, ctx);
165
+		close(fd);
166
+		if(!ctx->engine->keeptmp && cli_unlink(name))
167
+		    found = CL_EUNLINK;
168
+
169
+		free(name);
170
+		if(found != CL_CLEAN)
171
+		    break;
172
+	    }
173
+	}
174
+	IAlloc_Free(&allocImp, outBuffer);
175
+    }
176
+    SzArEx_Free(&db, &allocImp);
177
+    if(namelen > UTFBUFSZ)
178
+	free(utf16name);
179
+
180
+    if (res == SZ_OK)
181
+	cli_dbgmsg("cli_7unz: completed successfully\n");
182
+    else if (res == SZ_ERROR_UNSUPPORTED)
183
+	cli_dbgmsg("cli_7unz: unsupported\n");
184
+    else if (res == SZ_ERROR_MEM)
185
+	cli_dbgmsg("cli_7unz: oom\n");
186
+    else if (res == SZ_ERROR_CRC)
187
+	cli_dbgmsg("cli_7unz: crc mismatch\n");
188
+    else
189
+	cli_dbgmsg("cli_7unz: error %d\n", res);
190
+
191
+    return found;
192
+}
0 193
new file mode 100644
... ...
@@ -0,0 +1,32 @@
0
+/*
1
+ *  Copyright (C) 2011 Sourcefire, Inc.
2
+ *
3
+ *  Authors: aCaB
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#ifndef __7Z_IFACE_H
21
+#define __7Z_IFACE_H
22
+
23
+#if HAVE_CONFIG_H
24
+#include "clamav-config.h"
25
+#endif
26
+
27
+#include "others.h"
28
+
29
+int cli_7unz (cli_ctx *, size_t);
30
+
31
+#endif
... ...
@@ -281,36 +281,39 @@ libclamav_la_SOURCES = \
281 281
 	hashtab.h \
282 282
 	dconf.c \
283 283
 	dconf.h \
284
-	7z/LzmaDec.c \
285
-	7z/LzmaDec.h \
286
-	7z/Types.h \
287 284
 	lzma_iface.c \
288 285
 	lzma_iface.h \
289
-	7z.c \
290
-	7z.h \
286
+	7z_iface.c \
287
+	7z_iface.h \
288
+	7z/7z.h \
289
+	7z/7zAlloc.c \
290
+	7z/7zAlloc.h \
291
+	7z/7zBuf.c \
292
+	7z/7zBuf.h \
293
+	7z/7zBuf2.c \
294
+	7z/7zCrc.c \
295
+	7z/7zCrc.h \
296
+	7z/7zDec.c \
291 297
 	7z/7zFile.c \
292 298
 	7z/7zFile.h \
299
+	7z/7zIn.c \
293 300
 	7z/7zStream.c \
294
-	7z/CpuArch.h \
295
-	7z/7zCrc.c \
296
-	7z/7zCrc.h \
297
-	7z/7zBuf.c \
298
-	7z/7zBuf.h \
301
+	7z/7zVersion.h \
299 302
 	7z/Bcj2.c \
300 303
 	7z/Bcj2.h \
301 304
 	7z/Bra.c \
302 305
 	7z/Bra.h \
303 306
 	7z/Bra86.c \
304
-	7z/Archive/7z/7zIn.c \
305
-	7z/Archive/7z/7zIn.h \
306
-	7z/Archive/7z/7zDecode.c \
307
-	7z/Archive/7z/7zDecode.h \
308
-	7z/Archive/7z/7zItem.c \
309
-	7z/Archive/7z/7zItem.h \
310
-	7z/Archive/7z/7zHeader.c \
311
-	7z/Archive/7z/7zHeader.h \
312
-	7z/Archive/7z/7zExtract.c \
313
-	7z/Archive/7z/7zExtract.h \
307
+	7z/CpuArch.h \
308
+	7z/Lzma2Dec.c \
309
+	7z/Lzma2Dec.h \
310
+	7z/LzmaDec.c \
311
+	7z/LzmaDec.h \
312
+	7z/Ppmd.h \
313
+	7z/Ppmd7.c \
314
+	7z/Ppmd7.h \
315
+	7z/Ppmd7Dec.c \
316
+	7z/Types.h \
314 317
 	explode.c \
315 318
 	explode.h \
316 319
 	textnorm.c \
... ...
@@ -374,6 +377,8 @@ libclamav_la_SOURCES = \
374 374
 	iso9660.h \
375 375
 	arc4.c \
376 376
 	arc4.h \
377
+	rijndael.c \
378
+	rijndael.h \
377 379
 	crtmgr.c \
378 380
 	crtmgr.h \
379 381
 	asn1.c \
... ...
@@ -139,27 +139,26 @@ am__libclamav_la_SOURCES_DIST = clamav.h matcher-ac.c matcher-ac.h \
139 139
 	regex_list.c regex_list.h regex_suffix.c regex_suffix.h \
140 140
 	mspack.c mspack.h cab.c cab.h entconv.c entconv.h entitylist.h \
141 141
 	encoding_aliases.h hashtab.c hashtab.h dconf.c dconf.h \
142
-	7z/LzmaDec.c 7z/LzmaDec.h 7z/Types.h lzma_iface.c lzma_iface.h \
143
-	7z.c 7z.h 7z/7zFile.c 7z/7zFile.h 7z/7zStream.c 7z/CpuArch.h \
144
-	7z/7zCrc.c 7z/7zCrc.h 7z/7zBuf.c 7z/7zBuf.h 7z/Bcj2.c \
145
-	7z/Bcj2.h 7z/Bra.c 7z/Bra.h 7z/Bra86.c 7z/Archive/7z/7zIn.c \
146
-	7z/Archive/7z/7zIn.h 7z/Archive/7z/7zDecode.c \
147
-	7z/Archive/7z/7zDecode.h 7z/Archive/7z/7zItem.c \
148
-	7z/Archive/7z/7zItem.h 7z/Archive/7z/7zHeader.c \
149
-	7z/Archive/7z/7zHeader.h 7z/Archive/7z/7zExtract.c \
150
-	7z/Archive/7z/7zExtract.h explode.c explode.h textnorm.c \
151
-	textnorm.h dlp.c dlp.h jsparse/js-norm.c jsparse/js-norm.h \
152
-	jsparse/lexglobal.h jsparse/textbuf.h uniq.c uniq.h version.c \
153
-	version.h mpool.c mpool.h filtering.h filtering.c fmap.c \
154
-	fmap.h perflogging.c perflogging.h default.h sha256.c sha256.h \
155
-	sha1.c sha1.h bignum.h bytecode.c bytecode.h bytecode_vm.c \
156
-	bytecode_priv.h clambc.h cpio.c cpio.h macho.c macho.h \
157
-	ishield.c ishield.h type_desc.h bcfeatures.h bytecode_api.c \
158
-	bytecode_api_decl.c bytecode_api.h bytecode_api_impl.h \
159
-	bytecode_hooks.h cache.c cache.h bytecode_detect.c \
160
-	bytecode_detect.h builtin_bytecodes.h events.c events.h swf.c \
161
-	swf.h jpeg.c jpeg.h png.c png.h iso9660.c iso9660.h arc4.c \
162
-	arc4.h crtmgr.c crtmgr.h asn1.c asn1.h bignum.c bignum_class.h
142
+	lzma_iface.c lzma_iface.h 7z_iface.c 7z_iface.h 7z/7z.h \
143
+	7z/7zAlloc.c 7z/7zAlloc.h 7z/7zBuf.c 7z/7zBuf.h 7z/7zBuf2.c \
144
+	7z/7zCrc.c 7z/7zCrc.h 7z/7zDec.c 7z/7zFile.c 7z/7zFile.h \
145
+	7z/7zIn.c 7z/7zStream.c 7z/7zVersion.h 7z/Bcj2.c 7z/Bcj2.h \
146
+	7z/Bra.c 7z/Bra.h 7z/Bra86.c 7z/CpuArch.h 7z/Lzma2Dec.c \
147
+	7z/Lzma2Dec.h 7z/LzmaDec.c 7z/LzmaDec.h 7z/Ppmd.h 7z/Ppmd7.c \
148
+	7z/Ppmd7.h 7z/Ppmd7Dec.c 7z/Types.h explode.c explode.h \
149
+	textnorm.c textnorm.h dlp.c dlp.h jsparse/js-norm.c \
150
+	jsparse/js-norm.h jsparse/lexglobal.h jsparse/textbuf.h uniq.c \
151
+	uniq.h version.c version.h mpool.c mpool.h filtering.h \
152
+	filtering.c fmap.c fmap.h perflogging.c perflogging.h \
153
+	default.h sha256.c sha256.h sha1.c sha1.h bignum.h bytecode.c \
154
+	bytecode.h bytecode_vm.c bytecode_priv.h clambc.h cpio.c \
155
+	cpio.h macho.c macho.h ishield.c ishield.h type_desc.h \
156
+	bcfeatures.h bytecode_api.c bytecode_api_decl.c bytecode_api.h \
157
+	bytecode_api_impl.h bytecode_hooks.h cache.c cache.h \
158
+	bytecode_detect.c bytecode_detect.h builtin_bytecodes.h \
159
+	events.c events.h swf.c swf.h jpeg.c jpeg.h png.c png.h \
160
+	iso9660.c iso9660.h arc4.c arc4.h rijndael.c rijndael.h \
161
+	crtmgr.c crtmgr.h asn1.c asn1.h bignum.c bignum_class.h
163 162
 @LINK_TOMMATH_FALSE@am__objects_1 = libclamav_la-bignum.lo
164 163
 am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
165 164
 	libclamav_la-matcher-bm.lo libclamav_la-matcher-hash.lo \
... ...
@@ -193,13 +192,14 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
193 193
 	libclamav_la-regex_suffix.lo libclamav_la-mspack.lo \
194 194
 	libclamav_la-cab.lo libclamav_la-entconv.lo \
195 195
 	libclamav_la-hashtab.lo libclamav_la-dconf.lo \
196
-	libclamav_la-LzmaDec.lo libclamav_la-lzma_iface.lo \
197
-	libclamav_la-7z.lo libclamav_la-7zFile.lo \
198
-	libclamav_la-7zStream.lo libclamav_la-7zCrc.lo \
199
-	libclamav_la-7zBuf.lo libclamav_la-Bcj2.lo libclamav_la-Bra.lo \
200
-	libclamav_la-Bra86.lo libclamav_la-7zIn.lo \
201
-	libclamav_la-7zDecode.lo libclamav_la-7zItem.lo \
202
-	libclamav_la-7zHeader.lo libclamav_la-7zExtract.lo \
196
+	libclamav_la-lzma_iface.lo libclamav_la-7z_iface.lo \
197
+	libclamav_la-7zAlloc.lo libclamav_la-7zBuf.lo \
198
+	libclamav_la-7zBuf2.lo libclamav_la-7zCrc.lo \
199
+	libclamav_la-7zDec.lo libclamav_la-7zFile.lo \
200
+	libclamav_la-7zIn.lo libclamav_la-7zStream.lo \
201
+	libclamav_la-Bcj2.lo libclamav_la-Bra.lo libclamav_la-Bra86.lo \
202
+	libclamav_la-Lzma2Dec.lo libclamav_la-LzmaDec.lo \
203
+	libclamav_la-Ppmd7.lo libclamav_la-Ppmd7Dec.lo \
203 204
 	libclamav_la-explode.lo libclamav_la-textnorm.lo \
204 205
 	libclamav_la-dlp.lo libclamav_la-js-norm.lo \
205 206
 	libclamav_la-uniq.lo libclamav_la-version.lo \
... ...
@@ -213,7 +213,8 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
213 213
 	libclamav_la-bytecode_detect.lo libclamav_la-events.lo \
214 214
 	libclamav_la-swf.lo libclamav_la-jpeg.lo libclamav_la-png.lo \
215 215
 	libclamav_la-iso9660.lo libclamav_la-arc4.lo \
216
-	libclamav_la-crtmgr.lo libclamav_la-asn1.lo $(am__objects_1)
216
+	libclamav_la-rijndael.lo libclamav_la-crtmgr.lo \
217
+	libclamav_la-asn1.lo $(am__objects_1)
217 218
 libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
218 219
 AM_V_lt = $(am__v_lt_$(V))
219 220
 am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
... ...
@@ -653,27 +654,26 @@ libclamav_la_SOURCES = clamav.h matcher-ac.c matcher-ac.h matcher-bm.c \
653 653
 	regex_list.c regex_list.h regex_suffix.c regex_suffix.h \
654 654
 	mspack.c mspack.h cab.c cab.h entconv.c entconv.h entitylist.h \
655 655
 	encoding_aliases.h hashtab.c hashtab.h dconf.c dconf.h \
656
-	7z/LzmaDec.c 7z/LzmaDec.h 7z/Types.h lzma_iface.c lzma_iface.h \
657
-	7z.c 7z.h 7z/7zFile.c 7z/7zFile.h 7z/7zStream.c 7z/CpuArch.h \
658
-	7z/7zCrc.c 7z/7zCrc.h 7z/7zBuf.c 7z/7zBuf.h 7z/Bcj2.c \
659
-	7z/Bcj2.h 7z/Bra.c 7z/Bra.h 7z/Bra86.c 7z/Archive/7z/7zIn.c \
660
-	7z/Archive/7z/7zIn.h 7z/Archive/7z/7zDecode.c \
661
-	7z/Archive/7z/7zDecode.h 7z/Archive/7z/7zItem.c \
662
-	7z/Archive/7z/7zItem.h 7z/Archive/7z/7zHeader.c \
663
-	7z/Archive/7z/7zHeader.h 7z/Archive/7z/7zExtract.c \
664
-	7z/Archive/7z/7zExtract.h explode.c explode.h textnorm.c \
665
-	textnorm.h dlp.c dlp.h jsparse/js-norm.c jsparse/js-norm.h \
666
-	jsparse/lexglobal.h jsparse/textbuf.h uniq.c uniq.h version.c \
667
-	version.h mpool.c mpool.h filtering.h filtering.c fmap.c \
668
-	fmap.h perflogging.c perflogging.h default.h sha256.c sha256.h \
669
-	sha1.c sha1.h bignum.h bytecode.c bytecode.h bytecode_vm.c \
670
-	bytecode_priv.h clambc.h cpio.c cpio.h macho.c macho.h \
671
-	ishield.c ishield.h type_desc.h bcfeatures.h bytecode_api.c \
672
-	bytecode_api_decl.c bytecode_api.h bytecode_api_impl.h \
673
-	bytecode_hooks.h cache.c cache.h bytecode_detect.c \
674
-	bytecode_detect.h builtin_bytecodes.h events.c events.h swf.c \
675
-	swf.h jpeg.c jpeg.h png.c png.h iso9660.c iso9660.h arc4.c \
676
-	arc4.h crtmgr.c crtmgr.h asn1.c asn1.h $(am__append_7)
656
+	lzma_iface.c lzma_iface.h 7z_iface.c 7z_iface.h 7z/7z.h \
657
+	7z/7zAlloc.c 7z/7zAlloc.h 7z/7zBuf.c 7z/7zBuf.h 7z/7zBuf2.c \
658
+	7z/7zCrc.c 7z/7zCrc.h 7z/7zDec.c 7z/7zFile.c 7z/7zFile.h \
659
+	7z/7zIn.c 7z/7zStream.c 7z/7zVersion.h 7z/Bcj2.c 7z/Bcj2.h \
660
+	7z/Bra.c 7z/Bra.h 7z/Bra86.c 7z/CpuArch.h 7z/Lzma2Dec.c \
661
+	7z/Lzma2Dec.h 7z/LzmaDec.c 7z/LzmaDec.h 7z/Ppmd.h 7z/Ppmd7.c \
662
+	7z/Ppmd7.h 7z/Ppmd7Dec.c 7z/Types.h explode.c explode.h \
663
+	textnorm.c textnorm.h dlp.c dlp.h jsparse/js-norm.c \
664
+	jsparse/js-norm.h jsparse/lexglobal.h jsparse/textbuf.h uniq.c \
665
+	uniq.h version.c version.h mpool.c mpool.h filtering.h \
666
+	filtering.c fmap.c fmap.h perflogging.c perflogging.h \
667
+	default.h sha256.c sha256.h sha1.c sha1.h bignum.h bytecode.c \
668
+	bytecode.h bytecode_vm.c bytecode_priv.h clambc.h cpio.c \
669
+	cpio.h macho.c macho.h ishield.c ishield.h type_desc.h \
670
+	bcfeatures.h bytecode_api.c bytecode_api_decl.c bytecode_api.h \
671
+	bytecode_api_impl.h bytecode_hooks.h cache.c cache.h \
672
+	bytecode_detect.c bytecode_detect.h builtin_bytecodes.h \
673
+	events.c events.h swf.c swf.h jpeg.c jpeg.h png.c png.h \
674
+	iso9660.c iso9660.h arc4.c arc4.h rijndael.c rijndael.h \
675
+	crtmgr.c crtmgr.h asn1.c asn1.h $(am__append_7)
677 676
 noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la libclamav_nocxx.la
678 677
 COMMON_CLEANFILES = version.h version.h.tmp *.gcda *.gcno
679 678
 @MAINTAINER_MODE_TRUE@BUILT_SOURCES = jsparse/generated/operators.h jsparse/generated/keywords.h jsparse-keywords.gperf
... ...
@@ -793,20 +793,22 @@ distclean-compile:
793 793
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-regfree.Plo@am__quote@
794 794
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-str.Plo@am__quote@
795 795
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_internal_utils_nothreads_la-strlcpy.Plo@am__quote@
796
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7z.Plo@am__quote@
796
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zAlloc.Plo@am__quote@
797 797
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zBuf.Plo@am__quote@
798
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zBuf2.Plo@am__quote@
798 799
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zCrc.Plo@am__quote@
799
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zDecode.Plo@am__quote@
800
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zExtract.Plo@am__quote@
800
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zDec.Plo@am__quote@
801 801
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zFile.Plo@am__quote@
802
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zHeader.Plo@am__quote@
803 802
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zIn.Plo@am__quote@
804
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zItem.Plo@am__quote@
805 803
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7zStream.Plo@am__quote@
804
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-7z_iface.Plo@am__quote@
806 805
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-Bcj2.Plo@am__quote@
807 806
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-Bra.Plo@am__quote@
808 807
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-Bra86.Plo@am__quote@
808
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-Lzma2Dec.Plo@am__quote@
809 809
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-LzmaDec.Plo@am__quote@
810
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-Ppmd7.Plo@am__quote@
811
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-Ppmd7Dec.Plo@am__quote@
810 812
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-arc4.Plo@am__quote@
811 813
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-asn1.Plo@am__quote@
812 814
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-aspack.Plo@am__quote@
... ...
@@ -877,6 +879,7 @@ distclean-compile:
877 877
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-rebuildpe.Plo@am__quote@
878 878
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-regex_list.Plo@am__quote@
879 879
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-regex_suffix.Plo@am__quote@
880
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-rijndael.Plo@am__quote@
880 881
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-rtf.Plo@am__quote@
881 882
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-scanners.Plo@am__quote@
882 883
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-sha1.Plo@am__quote@
... ...
@@ -1448,14 +1451,6 @@ libclamav_la-dconf.lo: dconf.c
1448 1448
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1449 1449
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-dconf.lo `test -f 'dconf.c' || echo '$(srcdir)/'`dconf.c
1450 1450
 
1451
-libclamav_la-LzmaDec.lo: 7z/LzmaDec.c
1452
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-LzmaDec.lo -MD -MP -MF $(DEPDIR)/libclamav_la-LzmaDec.Tpo -c -o libclamav_la-LzmaDec.lo `test -f '7z/LzmaDec.c' || echo '$(srcdir)/'`7z/LzmaDec.c
1453
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-LzmaDec.Tpo $(DEPDIR)/libclamav_la-LzmaDec.Plo
1454
-@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1455
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/LzmaDec.c' object='libclamav_la-LzmaDec.lo' libtool=yes @AMDEPBACKSLASH@
1456
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1457
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-LzmaDec.lo `test -f '7z/LzmaDec.c' || echo '$(srcdir)/'`7z/LzmaDec.c
1458
-
1459 1451
 libclamav_la-lzma_iface.lo: lzma_iface.c
1460 1452
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-lzma_iface.lo -MD -MP -MF $(DEPDIR)/libclamav_la-lzma_iface.Tpo -c -o libclamav_la-lzma_iface.lo `test -f 'lzma_iface.c' || echo '$(srcdir)/'`lzma_iface.c
1461 1453
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-lzma_iface.Tpo $(DEPDIR)/libclamav_la-lzma_iface.Plo
... ...
@@ -1464,29 +1459,37 @@ libclamav_la-lzma_iface.lo: lzma_iface.c
1464 1464
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1465 1465
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-lzma_iface.lo `test -f 'lzma_iface.c' || echo '$(srcdir)/'`lzma_iface.c
1466 1466
 
1467
-libclamav_la-7z.lo: 7z.c
1468
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7z.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7z.Tpo -c -o libclamav_la-7z.lo `test -f '7z.c' || echo '$(srcdir)/'`7z.c
1469
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7z.Tpo $(DEPDIR)/libclamav_la-7z.Plo
1467
+libclamav_la-7z_iface.lo: 7z_iface.c
1468
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7z_iface.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7z_iface.Tpo -c -o libclamav_la-7z_iface.lo `test -f '7z_iface.c' || echo '$(srcdir)/'`7z_iface.c
1469
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7z_iface.Tpo $(DEPDIR)/libclamav_la-7z_iface.Plo
1470 1470
 @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1471
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z.c' object='libclamav_la-7z.lo' libtool=yes @AMDEPBACKSLASH@
1471
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z_iface.c' object='libclamav_la-7z_iface.lo' libtool=yes @AMDEPBACKSLASH@
1472 1472
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1473
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7z.lo `test -f '7z.c' || echo '$(srcdir)/'`7z.c
1473
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7z_iface.lo `test -f '7z_iface.c' || echo '$(srcdir)/'`7z_iface.c
1474 1474
 
1475
-libclamav_la-7zFile.lo: 7z/7zFile.c
1476
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zFile.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zFile.Tpo -c -o libclamav_la-7zFile.lo `test -f '7z/7zFile.c' || echo '$(srcdir)/'`7z/7zFile.c
1477
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zFile.Tpo $(DEPDIR)/libclamav_la-7zFile.Plo
1475
+libclamav_la-7zAlloc.lo: 7z/7zAlloc.c
1476
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zAlloc.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zAlloc.Tpo -c -o libclamav_la-7zAlloc.lo `test -f '7z/7zAlloc.c' || echo '$(srcdir)/'`7z/7zAlloc.c
1477
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zAlloc.Tpo $(DEPDIR)/libclamav_la-7zAlloc.Plo
1478 1478
 @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1479
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zFile.c' object='libclamav_la-7zFile.lo' libtool=yes @AMDEPBACKSLASH@
1479
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zAlloc.c' object='libclamav_la-7zAlloc.lo' libtool=yes @AMDEPBACKSLASH@
1480 1480
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1481
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zFile.lo `test -f '7z/7zFile.c' || echo '$(srcdir)/'`7z/7zFile.c
1481
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zAlloc.lo `test -f '7z/7zAlloc.c' || echo '$(srcdir)/'`7z/7zAlloc.c
1482 1482
 
1483
-libclamav_la-7zStream.lo: 7z/7zStream.c
1484
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zStream.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zStream.Tpo -c -o libclamav_la-7zStream.lo `test -f '7z/7zStream.c' || echo '$(srcdir)/'`7z/7zStream.c
1485
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zStream.Tpo $(DEPDIR)/libclamav_la-7zStream.Plo
1483
+libclamav_la-7zBuf.lo: 7z/7zBuf.c
1484
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zBuf.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zBuf.Tpo -c -o libclamav_la-7zBuf.lo `test -f '7z/7zBuf.c' || echo '$(srcdir)/'`7z/7zBuf.c
1485
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zBuf.Tpo $(DEPDIR)/libclamav_la-7zBuf.Plo
1486 1486
 @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1487
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zStream.c' object='libclamav_la-7zStream.lo' libtool=yes @AMDEPBACKSLASH@
1487
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zBuf.c' object='libclamav_la-7zBuf.lo' libtool=yes @AMDEPBACKSLASH@
1488 1488
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1489
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zStream.lo `test -f '7z/7zStream.c' || echo '$(srcdir)/'`7z/7zStream.c
1489
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zBuf.lo `test -f '7z/7zBuf.c' || echo '$(srcdir)/'`7z/7zBuf.c
1490
+
1491
+libclamav_la-7zBuf2.lo: 7z/7zBuf2.c
1492
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zBuf2.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zBuf2.Tpo -c -o libclamav_la-7zBuf2.lo `test -f '7z/7zBuf2.c' || echo '$(srcdir)/'`7z/7zBuf2.c
1493
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zBuf2.Tpo $(DEPDIR)/libclamav_la-7zBuf2.Plo
1494
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1495
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zBuf2.c' object='libclamav_la-7zBuf2.lo' libtool=yes @AMDEPBACKSLASH@
1496
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1497
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zBuf2.lo `test -f '7z/7zBuf2.c' || echo '$(srcdir)/'`7z/7zBuf2.c
1490 1498
 
1491 1499
 libclamav_la-7zCrc.lo: 7z/7zCrc.c
1492 1500
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zCrc.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zCrc.Tpo -c -o libclamav_la-7zCrc.lo `test -f '7z/7zCrc.c' || echo '$(srcdir)/'`7z/7zCrc.c
... ...
@@ -1496,13 +1499,37 @@ libclamav_la-7zCrc.lo: 7z/7zCrc.c
1496 1496
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1497 1497
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zCrc.lo `test -f '7z/7zCrc.c' || echo '$(srcdir)/'`7z/7zCrc.c
1498 1498
 
1499
-libclamav_la-7zBuf.lo: 7z/7zBuf.c
1500
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zBuf.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zBuf.Tpo -c -o libclamav_la-7zBuf.lo `test -f '7z/7zBuf.c' || echo '$(srcdir)/'`7z/7zBuf.c
1501
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zBuf.Tpo $(DEPDIR)/libclamav_la-7zBuf.Plo
1499
+libclamav_la-7zDec.lo: 7z/7zDec.c
1500
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zDec.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zDec.Tpo -c -o libclamav_la-7zDec.lo `test -f '7z/7zDec.c' || echo '$(srcdir)/'`7z/7zDec.c
1501
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zDec.Tpo $(DEPDIR)/libclamav_la-7zDec.Plo
1502 1502
 @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1503
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zBuf.c' object='libclamav_la-7zBuf.lo' libtool=yes @AMDEPBACKSLASH@
1503
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zDec.c' object='libclamav_la-7zDec.lo' libtool=yes @AMDEPBACKSLASH@
1504 1504
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1505
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zBuf.lo `test -f '7z/7zBuf.c' || echo '$(srcdir)/'`7z/7zBuf.c
1505
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zDec.lo `test -f '7z/7zDec.c' || echo '$(srcdir)/'`7z/7zDec.c
1506
+
1507
+libclamav_la-7zFile.lo: 7z/7zFile.c
1508
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zFile.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zFile.Tpo -c -o libclamav_la-7zFile.lo `test -f '7z/7zFile.c' || echo '$(srcdir)/'`7z/7zFile.c
1509
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zFile.Tpo $(DEPDIR)/libclamav_la-7zFile.Plo
1510
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1511
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zFile.c' object='libclamav_la-7zFile.lo' libtool=yes @AMDEPBACKSLASH@
1512
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1513
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zFile.lo `test -f '7z/7zFile.c' || echo '$(srcdir)/'`7z/7zFile.c
1514
+
1515
+libclamav_la-7zIn.lo: 7z/7zIn.c
1516
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zIn.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zIn.Tpo -c -o libclamav_la-7zIn.lo `test -f '7z/7zIn.c' || echo '$(srcdir)/'`7z/7zIn.c
1517
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zIn.Tpo $(DEPDIR)/libclamav_la-7zIn.Plo
1518
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1519
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zIn.c' object='libclamav_la-7zIn.lo' libtool=yes @AMDEPBACKSLASH@
1520
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1521
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zIn.lo `test -f '7z/7zIn.c' || echo '$(srcdir)/'`7z/7zIn.c
1522
+
1523
+libclamav_la-7zStream.lo: 7z/7zStream.c
1524
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zStream.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zStream.Tpo -c -o libclamav_la-7zStream.lo `test -f '7z/7zStream.c' || echo '$(srcdir)/'`7z/7zStream.c
1525
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zStream.Tpo $(DEPDIR)/libclamav_la-7zStream.Plo
1526
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1527
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/7zStream.c' object='libclamav_la-7zStream.lo' libtool=yes @AMDEPBACKSLASH@
1528
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1529
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zStream.lo `test -f '7z/7zStream.c' || echo '$(srcdir)/'`7z/7zStream.c
1506 1530
 
1507 1531
 libclamav_la-Bcj2.lo: 7z/Bcj2.c
1508 1532
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-Bcj2.lo -MD -MP -MF $(DEPDIR)/libclamav_la-Bcj2.Tpo -c -o libclamav_la-Bcj2.lo `test -f '7z/Bcj2.c' || echo '$(srcdir)/'`7z/Bcj2.c
... ...
@@ -1528,45 +1555,37 @@ libclamav_la-Bra86.lo: 7z/Bra86.c
1528 1528
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1529 1529
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-Bra86.lo `test -f '7z/Bra86.c' || echo '$(srcdir)/'`7z/Bra86.c
1530 1530
 
1531
-libclamav_la-7zIn.lo: 7z/Archive/7z/7zIn.c
1532
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zIn.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zIn.Tpo -c -o libclamav_la-7zIn.lo `test -f '7z/Archive/7z/7zIn.c' || echo '$(srcdir)/'`7z/Archive/7z/7zIn.c
1533
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zIn.Tpo $(DEPDIR)/libclamav_la-7zIn.Plo
1534
-@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1535
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/Archive/7z/7zIn.c' object='libclamav_la-7zIn.lo' libtool=yes @AMDEPBACKSLASH@
1536
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1537
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zIn.lo `test -f '7z/Archive/7z/7zIn.c' || echo '$(srcdir)/'`7z/Archive/7z/7zIn.c
1538
-
1539
-libclamav_la-7zDecode.lo: 7z/Archive/7z/7zDecode.c
1540
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zDecode.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zDecode.Tpo -c -o libclamav_la-7zDecode.lo `test -f '7z/Archive/7z/7zDecode.c' || echo '$(srcdir)/'`7z/Archive/7z/7zDecode.c
1541
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zDecode.Tpo $(DEPDIR)/libclamav_la-7zDecode.Plo
1531
+libclamav_la-Lzma2Dec.lo: 7z/Lzma2Dec.c
1532
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-Lzma2Dec.lo -MD -MP -MF $(DEPDIR)/libclamav_la-Lzma2Dec.Tpo -c -o libclamav_la-Lzma2Dec.lo `test -f '7z/Lzma2Dec.c' || echo '$(srcdir)/'`7z/Lzma2Dec.c
1533
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-Lzma2Dec.Tpo $(DEPDIR)/libclamav_la-Lzma2Dec.Plo
1542 1534
 @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1543
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/Archive/7z/7zDecode.c' object='libclamav_la-7zDecode.lo' libtool=yes @AMDEPBACKSLASH@
1535
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/Lzma2Dec.c' object='libclamav_la-Lzma2Dec.lo' libtool=yes @AMDEPBACKSLASH@
1544 1536
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1545
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zDecode.lo `test -f '7z/Archive/7z/7zDecode.c' || echo '$(srcdir)/'`7z/Archive/7z/7zDecode.c
1537
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-Lzma2Dec.lo `test -f '7z/Lzma2Dec.c' || echo '$(srcdir)/'`7z/Lzma2Dec.c
1546 1538
 
1547
-libclamav_la-7zItem.lo: 7z/Archive/7z/7zItem.c
1548
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zItem.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zItem.Tpo -c -o libclamav_la-7zItem.lo `test -f '7z/Archive/7z/7zItem.c' || echo '$(srcdir)/'`7z/Archive/7z/7zItem.c
1549
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zItem.Tpo $(DEPDIR)/libclamav_la-7zItem.Plo
1539
+libclamav_la-LzmaDec.lo: 7z/LzmaDec.c
1540
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-LzmaDec.lo -MD -MP -MF $(DEPDIR)/libclamav_la-LzmaDec.Tpo -c -o libclamav_la-LzmaDec.lo `test -f '7z/LzmaDec.c' || echo '$(srcdir)/'`7z/LzmaDec.c
1541
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-LzmaDec.Tpo $(DEPDIR)/libclamav_la-LzmaDec.Plo
1550 1542
 @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1551
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/Archive/7z/7zItem.c' object='libclamav_la-7zItem.lo' libtool=yes @AMDEPBACKSLASH@
1543
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/LzmaDec.c' object='libclamav_la-LzmaDec.lo' libtool=yes @AMDEPBACKSLASH@
1552 1544
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1553
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zItem.lo `test -f '7z/Archive/7z/7zItem.c' || echo '$(srcdir)/'`7z/Archive/7z/7zItem.c
1545
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-LzmaDec.lo `test -f '7z/LzmaDec.c' || echo '$(srcdir)/'`7z/LzmaDec.c
1554 1546
 
1555
-libclamav_la-7zHeader.lo: 7z/Archive/7z/7zHeader.c
1556
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zHeader.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zHeader.Tpo -c -o libclamav_la-7zHeader.lo `test -f '7z/Archive/7z/7zHeader.c' || echo '$(srcdir)/'`7z/Archive/7z/7zHeader.c
1557
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zHeader.Tpo $(DEPDIR)/libclamav_la-7zHeader.Plo
1547
+libclamav_la-Ppmd7.lo: 7z/Ppmd7.c
1548
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-Ppmd7.lo -MD -MP -MF $(DEPDIR)/libclamav_la-Ppmd7.Tpo -c -o libclamav_la-Ppmd7.lo `test -f '7z/Ppmd7.c' || echo '$(srcdir)/'`7z/Ppmd7.c
1549
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-Ppmd7.Tpo $(DEPDIR)/libclamav_la-Ppmd7.Plo
1558 1550
 @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1559
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/Archive/7z/7zHeader.c' object='libclamav_la-7zHeader.lo' libtool=yes @AMDEPBACKSLASH@
1551
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/Ppmd7.c' object='libclamav_la-Ppmd7.lo' libtool=yes @AMDEPBACKSLASH@
1560 1552
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1561
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zHeader.lo `test -f '7z/Archive/7z/7zHeader.c' || echo '$(srcdir)/'`7z/Archive/7z/7zHeader.c
1553
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-Ppmd7.lo `test -f '7z/Ppmd7.c' || echo '$(srcdir)/'`7z/Ppmd7.c
1562 1554
 
1563
-libclamav_la-7zExtract.lo: 7z/Archive/7z/7zExtract.c
1564
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-7zExtract.lo -MD -MP -MF $(DEPDIR)/libclamav_la-7zExtract.Tpo -c -o libclamav_la-7zExtract.lo `test -f '7z/Archive/7z/7zExtract.c' || echo '$(srcdir)/'`7z/Archive/7z/7zExtract.c
1565
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-7zExtract.Tpo $(DEPDIR)/libclamav_la-7zExtract.Plo
1555
+libclamav_la-Ppmd7Dec.lo: 7z/Ppmd7Dec.c
1556
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-Ppmd7Dec.lo -MD -MP -MF $(DEPDIR)/libclamav_la-Ppmd7Dec.Tpo -c -o libclamav_la-Ppmd7Dec.lo `test -f '7z/Ppmd7Dec.c' || echo '$(srcdir)/'`7z/Ppmd7Dec.c
1557
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-Ppmd7Dec.Tpo $(DEPDIR)/libclamav_la-Ppmd7Dec.Plo
1566 1558
 @am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1567
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/Archive/7z/7zExtract.c' object='libclamav_la-7zExtract.lo' libtool=yes @AMDEPBACKSLASH@
1559
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='7z/Ppmd7Dec.c' object='libclamav_la-Ppmd7Dec.lo' libtool=yes @AMDEPBACKSLASH@
1568 1560
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1569
-@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-7zExtract.lo `test -f '7z/Archive/7z/7zExtract.c' || echo '$(srcdir)/'`7z/Archive/7z/7zExtract.c
1561
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-Ppmd7Dec.lo `test -f '7z/Ppmd7Dec.c' || echo '$(srcdir)/'`7z/Ppmd7Dec.c
1570 1562
 
1571 1563
 libclamav_la-explode.lo: explode.c
1572 1564
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-explode.lo -MD -MP -MF $(DEPDIR)/libclamav_la-explode.Tpo -c -o libclamav_la-explode.lo `test -f 'explode.c' || echo '$(srcdir)/'`explode.c
... ...
@@ -1784,6 +1803,14 @@ libclamav_la-arc4.lo: arc4.c
1784 1784
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1785 1785
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-arc4.lo `test -f 'arc4.c' || echo '$(srcdir)/'`arc4.c
1786 1786
 
1787
+libclamav_la-rijndael.lo: rijndael.c
1788
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-rijndael.lo -MD -MP -MF $(DEPDIR)/libclamav_la-rijndael.Tpo -c -o libclamav_la-rijndael.lo `test -f 'rijndael.c' || echo '$(srcdir)/'`rijndael.c
1789
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-rijndael.Tpo $(DEPDIR)/libclamav_la-rijndael.Plo
1790
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
1791
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='rijndael.c' object='libclamav_la-rijndael.lo' libtool=yes @AMDEPBACKSLASH@
1792
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1793
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-rijndael.lo `test -f 'rijndael.c' || echo '$(srcdir)/'`rijndael.c
1794
+
1787 1795
 libclamav_la-crtmgr.lo: crtmgr.c
1788 1796
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-crtmgr.lo -MD -MP -MF $(DEPDIR)/libclamav_la-crtmgr.Tpo -c -o libclamav_la-crtmgr.lo `test -f 'crtmgr.c' || echo '$(srcdir)/'`crtmgr.c
1789 1797
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-crtmgr.Tpo $(DEPDIR)/libclamav_la-crtmgr.Plo
... ...
@@ -92,8 +92,8 @@
92 92
 struct cli_asn1 {
93 93
     uint8_t type;
94 94
     unsigned int size;
95
-    void *content;
96
-    void *next;
95
+    const void *content;
96
+    const void *next;
97 97
 };
98 98
 
99 99
 static int map_sha1(fmap_t *map, void *data, unsigned int len, uint8_t sha1[SHA1_HASH_SIZE]) {
... ...
@@ -113,7 +113,7 @@ static int map_sha1(fmap_t *map, void *data, unsigned int len, uint8_t sha1[SHA1
113 113
     return 0;
114 114
 }
115 115
 
116
-static int map_md5(fmap_t *map, void *data, unsigned int len, uint8_t *md5) {
116
+static int map_md5(fmap_t *map, const void *data, unsigned int len, uint8_t *md5) {
117 117
     cli_md5_ctx ctx;
118 118
     if(!fmap_need_ptr_once(map, data, len)) {
119 119
 	cli_dbgmsg("map_md5: failed to read hash data\n");
... ...
@@ -131,10 +131,10 @@ static int map_md5(fmap_t *map, void *data, unsigned int len, uint8_t *md5) {
131 131
 }
132 132
 
133 133
 
134
-static int asn1_get_obj(fmap_t *map, void *asn1data, unsigned int *asn1len, struct cli_asn1 *obj) {
134
+static int asn1_get_obj(fmap_t *map, const void *asn1data, unsigned int *asn1len, struct cli_asn1 *obj) {
135 135
     unsigned int asn1_sz = *asn1len;
136 136
     unsigned int readbytes = MIN(6, asn1_sz), i;
137
-    uint8_t *data;
137
+    const uint8_t *data;
138 138
 
139 139
     if(asn1_sz < 2) {
140 140
 	cli_dbgmsg("asn1_get_obj: insufficient data length\n");
... ...
@@ -184,7 +184,7 @@ static int asn1_get_obj(fmap_t *map, void *asn1data, unsigned int *asn1len, stru
184 184
     return 0;
185 185
 }
186 186
 
187
-static int asn1_expect_objtype(fmap_t *map, void *asn1data, unsigned int *asn1len, struct cli_asn1 *obj, uint8_t type) {
187
+static int asn1_expect_objtype(fmap_t *map, const void *asn1data, unsigned int *asn1len, struct cli_asn1 *obj, uint8_t type) {
188 188
     int ret = asn1_get_obj(map, asn1data, asn1len, obj);
189 189
     if(ret)
190 190
 	return ret;
... ...
@@ -195,7 +195,7 @@ static int asn1_expect_objtype(fmap_t *map, void *asn1data, unsigned int *asn1le
195 195
     return 0;
196 196
 }
197 197
 
198
-static int asn1_expect_obj(fmap_t *map, void **asn1data, unsigned int *asn1len, uint8_t type, unsigned int size, const void *content) {
198
+static int asn1_expect_obj(fmap_t *map, const void **asn1data, unsigned int *asn1len, uint8_t type, unsigned int size, const void *content) {
199 199
     struct cli_asn1 obj;
200 200
     int ret = asn1_expect_objtype(map, *asn1data, asn1len, &obj, type);
201 201
     if(ret)
... ...
@@ -218,7 +218,7 @@ static int asn1_expect_obj(fmap_t *map, void **asn1data, unsigned int *asn1len,
218 218
     return 0;
219 219
 }
220 220
 
221
-static int asn1_expect_algo(fmap_t *map, void **asn1data, unsigned int *asn1len, unsigned int algo_size, const void *algo) {
221
+static int asn1_expect_algo(fmap_t *map, const void **asn1data, unsigned int *asn1len, unsigned int algo_size, const void *algo) {
222 222
     struct cli_asn1 obj;
223 223
     unsigned int avail;
224 224
     int ret;
... ...
@@ -239,7 +239,7 @@ static int asn1_expect_algo(fmap_t *map, void **asn1data, unsigned int *asn1len,
239 239
 }
240 240
 
241 241
 
242
-static int asn1_expect_rsa(fmap_t *map, void **asn1data, unsigned int *asn1len, cli_crt_hashtype *hashtype) {
242
+static int asn1_expect_rsa(fmap_t *map, const void **asn1data, unsigned int *asn1len, cli_crt_hashtype *hashtype) {
243 243
     struct cli_asn1 obj;
244 244
     unsigned int avail;
245 245
     int ret;
... ...
@@ -285,7 +285,7 @@ static int asn1_getnum(const char *s) {
285 285
     return (s[0] - '0')*10 + (s[1] - '0');
286 286
 }
287 287
 
288
-static int asn1_get_time(fmap_t *map, void **asn1data, unsigned int *size, time_t *tm) {
288
+static int asn1_get_time(fmap_t *map, const void **asn1data, unsigned int *size, time_t *tm) {
289 289
     struct cli_asn1 obj;
290 290
     int ret = asn1_get_obj(map, *asn1data, size, &obj);
291 291
     unsigned int len;
... ...
@@ -382,7 +382,7 @@ static int asn1_get_time(fmap_t *map, void **asn1data, unsigned int *size, time_
382 382
     return 0;
383 383
 }
384 384
 
385
-static int asn1_get_rsa_pubkey(fmap_t *map, void **asn1data, unsigned int *size, cli_crt *x509) {
385
+static int asn1_get_rsa_pubkey(fmap_t *map, const void **asn1data, unsigned int *size, cli_crt *x509) {
386 386
     struct cli_asn1 obj;
387 387
     unsigned int avail, avail2;
388 388
 
... ...
@@ -459,13 +459,13 @@ static int asn1_get_rsa_pubkey(fmap_t *map, void **asn1data, unsigned int *size,
459 459
     return 0;
460 460
 }
461 461
 
462
-static int asn1_get_x509(fmap_t *map, void **asn1data, unsigned int *size, crtmgr *master, crtmgr *other) {
462
+static int asn1_get_x509(fmap_t *map, const void **asn1data, unsigned int *size, crtmgr *master, crtmgr *other) {
463 463
     struct cli_asn1 crt, tbs, obj;
464 464
     unsigned int avail, tbssize, issuersize;
465 465
     cli_crt_hashtype hashtype1, hashtype2;
466 466
     cli_crt x509;
467 467
     uint8_t *tbsdata;
468
-    void *next, *issuer;
468
+    const void *next, *issuer;
469 469
 
470 470
     if(cli_crt_init(&x509))
471 471
 	return 1;
... ...
@@ -593,7 +593,7 @@ static int asn1_get_x509(fmap_t *map, void **asn1data, unsigned int *size, crtmg
593 593
     return 1;
594 594
 }
595 595
 
596
-static int asn1_parse_mscat(fmap_t *map, void *start, unsigned int size, crtmgr *cmgr, int embedded, void **hashes, unsigned int *hashes_size) {
596
+static int asn1_parse_mscat(fmap_t *map, const void *start, unsigned int size, crtmgr *cmgr, int embedded, const void **hashes, unsigned int *hashes_size) {
597 597
     struct cli_asn1 asn1, deep, deeper;
598 598
     uint8_t sha1[SHA1_HASH_SIZE], issuer[SHA1_HASH_SIZE], md[SHA1_HASH_SIZE], *message, *attrs;
599 599
     unsigned int dsize, message_size, attrs_size;
... ...
@@ -1116,7 +1116,7 @@ static int asn1_parse_mscat(fmap_t *map, void *start, unsigned int size, crtmgr
1116 1116
     return 1;
1117 1117
 }
1118 1118
 
1119
-int asn1_load_mscat(fmap_t *map, void *start, unsigned int size, struct cl_engine *engine) {
1119
+int asn1_load_mscat(fmap_t *map, const void *start, unsigned int size, struct cl_engine *engine) {
1120 1120
     struct cli_asn1 c;
1121 1121
     char *virname;
1122 1122
     struct cli_matcher *db;
... ...
@@ -1269,10 +1269,10 @@ int asn1_load_mscat(fmap_t *map, void *start, unsigned int size, struct cl_engin
1269 1269
     return 0;
1270 1270
 }
1271 1271
 
1272
-int asn1_check_mscat(fmap_t *map, void *start, unsigned int size, uint8_t *computed_sha1) {
1272
+int asn1_check_mscat(fmap_t *map, const void *start, unsigned int size, uint8_t *computed_sha1) {
1273 1273
     unsigned int content_size;
1274 1274
     struct cli_asn1 c;
1275
-    void *content;
1275
+    const void *content;
1276 1276
     crtmgr certs;
1277 1277
     int ret;
1278 1278
 
... ...
@@ -24,7 +24,7 @@
24 24
 #include "others.h"
25 25
 #include "fmap.h"
26 26
 
27
-int asn1_load_mscat(fmap_t *map, void *start, unsigned int size, struct cl_engine *engine);
28
-int asn1_check_mscat(fmap_t *map, void *start, unsigned int size, uint8_t *computed_sha1);
27
+int asn1_load_mscat(fmap_t *map, const void *start, unsigned int size, struct cl_engine *engine);
28
+int asn1_check_mscat(fmap_t *map, const void *start, unsigned int size, uint8_t *computed_sha1);
29 29
 
30 30
 #endif
... ...
@@ -130,7 +130,9 @@ enum pdf_objflags {
130 130
     OBJ_TRUNCATED,
131 131
     OBJ_FORCEDUMP,
132 132
     OBJ_FILTER_STANDARD,
133
-    OBJ_LAUNCHACTION
133
+    OBJ_LAUNCHACTION,
134
+    OBJ_PAGE,
135
+    OBJ_CONTENTS
134 136
 };
135 137
 
136 138
 #ifdef __CLAMBC__
... ...
@@ -37,8 +37,8 @@
37 37
 #include "mspack.h"
38 38
 #include "cab.h"
39 39
 
40
-#define EC32(x) le32_to_host(x) /* Convert little endian to host */
41
-#define EC16(x) le16_to_host(x)
40
+#define EC32(x) cli_readint32(&x) /* Convert little endian to host */
41
+#define EC16(x) cli_readint16(&x)
42 42
 
43 43
 /* hard limits */
44 44
 #define CAB_FOLDER_LIMIT    5000
... ...
@@ -92,43 +92,35 @@ struct cab_block_hdr
92 92
     uint16_t	cbUncomp;   /* number of uncompressed bytes */
93 93
 };
94 94
 
95
-static char *cab_readstr(int fd, int *ret)
95
+static char *cab_readstr(fmap_t *map, off_t *offset, int *ret)
96 96
 {
97
-	int i, bread, found = 0;
98
-	char buff[256], *str;
99
-	off_t pos;
97
+	int i;
98
+	char *str, *retstr;
100 99
 
101
-
102
-    if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
103
-	*ret = CL_ESEEK;
100
+    if(!(str = fmap_need_offstr(map, *offset, 256))) {
101
+	*ret = CL_EFORMAT;
104 102
 	return NULL;
105 103
     }
106 104
 
107
-    bread = read(fd, buff, sizeof(buff));
108
-    for(i = 0; i < bread; i++) {
109
-	if(!buff[i]) {
110
-	    found = 1;
111
-	    break;
112
-	}
113
-    }
114
-
115
-    if(!found) {
105
+    i = strlen(str) + 1;
106
+    if(i>=255) {
107
+	fmap_unneed_ptr(map, str, i);
116 108
 	*ret = CL_EFORMAT;
117 109
 	return NULL;
118 110
     }
119 111
 
120
-    if(lseek(fd, (off_t) (pos + i + 1), SEEK_SET) == -1) {
121
-	*ret = CL_EFORMAT; /* most likely a corrupted file */
122
-	return NULL;
123
-    }
112
+    *offset += i;
113
+    if((retstr = cli_malloc(i)))
114
+	memcpy(retstr, str, i);
115
+    fmap_unneed_ptr(map, str, i);
124 116
 
125
-    if(!(str = cli_strdup(buff))) {
117
+    if(!retstr) {
126 118
 	*ret = CL_EMEM;
127 119
 	return NULL;
128 120
     }
129 121
 
130 122
     *ret = CL_SUCCESS;
131
-    return str;
123
+    return retstr;
132 124
 }
133 125
 
134 126
 static int cab_chkname(char *name, int san)
... ...
@@ -184,55 +176,44 @@ void cab_free(struct cab_archive *cab)
184 184
     }
185 185
 }
186 186
 
187
-int cab_open(int fd, off_t offset, struct cab_archive *cab)
187
+int cab_open(fmap_t *map, off_t offset, struct cab_archive *cab)
188 188
 {
189 189
 	unsigned int i, folders = 0;
190 190
 	struct cab_file *file, *lfile = NULL;
191 191
 	struct cab_folder *folder, *lfolder = NULL;
192
-	struct cab_hdr hdr;
193
-	struct cab_hdr_opt hdr_opt;
194
-	struct cab_folder_hdr folder_hdr;
195
-	struct cab_file_hdr file_hdr;
196
-	struct stat sb;
192
+	struct cab_hdr *hdr;
193
+	struct cab_hdr_opt *hdr_opt;
197 194
 	uint16_t fidx;
195
+	uint32_t coffFiles;
198 196
 	char *pt;
199 197
 	int ret;
200
-	off_t resfold = 0, rsize;
201
-
202
-
203
-    if(lseek(fd, offset, SEEK_SET) == -1) {
204
-	cli_errmsg("cab_open: Can't lseek to %u (offset)\n", (unsigned int) offset);
205
-	return CL_ESEEK;
206
-    }
198
+	off_t resfold = 0, rsize, cur_offset = offset;
207 199
 
208
-    if(cli_readn(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
200
+    if(!(hdr=fmap_need_off_once(map, cur_offset, sizeof(*hdr)))) {
209 201
 	cli_dbgmsg("cab_open: Can't read cabinet header\n");
210 202
 	return CL_EFORMAT; /* most likely a corrupted file */
211 203
     }
204
+    cur_offset += sizeof(*hdr);
212 205
 
213
-    if(EC32(hdr.signature) != 0x4643534d) {
206
+    if(EC32(hdr->signature) != 0x4643534d) {
214 207
 	cli_dbgmsg("cab_open: Incorrect CAB signature\n");
215 208
 	return CL_EFORMAT;
216 209
     } else {
217 210
 	cli_dbgmsg("CAB: -------------- Cabinet file ----------------\n");
218 211
     }
219 212
 
220
-    if(fstat(fd, &sb) == -1) {
221
-	cli_errmsg("cab_open: Can't fstat descriptor %d\n", fd);
222
-	return CL_ESTAT;
223
-    }
224
-    rsize = sb.st_size;
213
+    rsize = map->len;
225 214
 
226 215
     memset(cab, 0, sizeof(struct cab_archive));
227 216
 
228
-    cab->length = EC32(hdr.cbCabinet);
217
+    cab->length = EC32(hdr->cbCabinet);
229 218
     cli_dbgmsg("CAB: Cabinet length: %u\n", cab->length);
230 219
     if((off_t) cab->length > rsize) {
231 220
 	cli_dbgmsg("CAB: Truncating file size from %lu to %lu\n", (unsigned long int) cab->length, (unsigned long int) rsize);
232 221
 	cab->length = (uint32_t) rsize;
233 222
     }
234 223
 
235
-    cab->nfolders = EC16(hdr.cFolders);
224
+    cab->nfolders = EC16(hdr->cFolders);
236 225
     if(!cab->nfolders) {
237 226
 	cli_dbgmsg("cab_open: No folders in cabinet (fake cab?)\n");
238 227
 	return CL_EFORMAT;
... ...
@@ -244,7 +225,7 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
244 244
 	}
245 245
     }
246 246
 
247
-    cab->nfiles = EC16(hdr.cFiles);
247
+    cab->nfiles = EC16(hdr->cFiles);
248 248
     if(!cab->nfiles) {
249 249
 	cli_dbgmsg("cab_open: No files in cabinet (fake cab?)\n");
250 250
 	return CL_EFORMAT;
... ...
@@ -256,21 +237,24 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
256 256
 	}
257 257
     }
258 258
 
259
-    cli_dbgmsg("CAB: File format version: %u.%u\n", hdr.versionMajor, hdr.versionMinor);
259
+    cli_dbgmsg("CAB: File format version: %u.%u\n", hdr->versionMajor, hdr->versionMinor);
260
+
261
+    cab->flags = EC16(hdr->flags);
262
+    coffFiles = EC16(hdr->coffFiles);
260 263
 
261
-    cab->flags = EC16(hdr.flags);
262 264
     if(cab->flags & 0x0004) {
263
-	if(cli_readn(fd, &hdr_opt, sizeof(hdr_opt)) != sizeof(hdr_opt)) {
265
+	if(!(hdr_opt = fmap_need_off_once(map, cur_offset, sizeof(*hdr_opt)))) {
264 266
 	    cli_dbgmsg("cab_open: Can't read file header (fake cab?)\n");
265 267
 	    return CL_EFORMAT; /* most likely a corrupted file */
266 268
 	}
267 269
 
268
-	cab->reshdr = EC16(hdr_opt.cbCFHeader);
269
-	resfold = hdr_opt.cbCFFolder;
270
-	cab->resdata = hdr_opt.cbCFData;
270
+	cab->reshdr = EC16(hdr_opt->cbCFHeader);
271
+	resfold = hdr_opt->cbCFFolder;
272
+	cab->resdata = hdr_opt->cbCFData;
271 273
 
274
+	cur_offset += sizeof(*hdr_opt) + cab->reshdr;
272 275
 	if(cab->reshdr) {
273
-	    if(lseek(fd, cab->reshdr, SEEK_CUR) == -1) {
276
+	    if(cab->reshdr >= rsize) {
274 277
 		cli_dbgmsg("cab_open: Can't lseek to %u (fake cab?)\n", cab->reshdr);
275 278
 		return CL_EFORMAT; /* most likely a corrupted file */
276 279
 	    }
... ...
@@ -279,7 +263,7 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
279 279
 
280 280
     if(cab->flags & 0x0001) { /* preceding cabinet */
281 281
 	/* name */
282
-	pt = cab_readstr(fd, &ret);
282
+	pt = cab_readstr(map, &cur_offset, &ret);
283 283
 	if(ret)
284 284
 	    return ret;
285 285
 	if(cab_chkname(pt, 0))
... ...
@@ -288,7 +272,7 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
288 288
 	    cli_dbgmsg("CAB: Preceding cabinet name: %s\n", pt);
289 289
 	free(pt);
290 290
 	/* info */
291
-	pt = cab_readstr(fd, &ret);
291
+	pt = cab_readstr(map, &cur_offset, &ret);
292 292
 	if(ret)
293 293
 	    return ret;
294 294
 	if(cab_chkname(pt, 0))
... ...
@@ -300,7 +284,7 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
300 300
 
301 301
     if(cab->flags & 0x0002) { /* next cabinet */
302 302
 	/* name */
303
-	pt = cab_readstr(fd, &ret);
303
+	pt = cab_readstr(map, &cur_offset, &ret);
304 304
 	if(ret)
305 305
 	    return ret;
306 306
 	if(cab_chkname(pt, 0))
... ...
@@ -309,7 +293,7 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
309 309
 	    cli_dbgmsg("CAB: Next cabinet name: %s\n", pt);
310 310
 	free(pt);
311 311
 	/* info */
312
-	pt = cab_readstr(fd, &ret);
312
+	pt = cab_readstr(map, &cur_offset, &ret);
313 313
 	if(ret)
314 314
 	    return ret;
315 315
 	if(cab_chkname(pt, 0))
... ...
@@ -321,24 +305,21 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
321 321
 
322 322
     /* folders */
323 323
     for(i = 0; i < cab->nfolders; i++) {
324
-	if(cli_readn(fd, &folder_hdr, sizeof(folder_hdr)) != sizeof(folder_hdr)) {
324
+	struct cab_folder_hdr *folder_hdr;
325
+
326
+	if(!(folder_hdr = fmap_need_off_once(map, cur_offset, sizeof(*folder_hdr)))) {
325 327
 	    cli_dbgmsg("cab_open: Can't read header for folder %u\n", i);
326 328
 	    break;
327 329
 	}
328 330
 
329
-	if(resfold) {
330
-	    if(lseek(fd, resfold, SEEK_CUR) == -1) {
331
-		cli_dbgmsg("cab_open: Can't lseek to %u (resfold)\n", (unsigned int) resfold);
332
-		break;
333
-	    }
334
-	}
331
+	cur_offset += sizeof(*folder_hdr) + resfold;
335 332
 
336
-	if(EC32(folder_hdr.coffCabStart) + offset > rsize) {
333
+	if(EC32(folder_hdr->coffCabStart) + offset > rsize) {
337 334
 	    cli_dbgmsg("CAB: Folder out of file\n");
338 335
 	    continue;
339 336
 	}
340 337
 
341
-	if((EC16(folder_hdr.typeCompress) & 0x000f) > 3) {
338
+	if((EC16(folder_hdr->typeCompress) & 0x000f) > 3) {
342 339
 	    cli_dbgmsg("CAB: Unknown compression method\n");
343 340
 	    continue;
344 341
 	}
... ...
@@ -351,9 +332,9 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
351 351
 	}
352 352
 
353 353
 	folder->cab = (struct cab_archive *) cab;
354
-	folder->offset = (off_t) EC32(folder_hdr.coffCabStart) + offset;
355
-	folder->nblocks = EC16(folder_hdr.cCFData);
356
-	folder->cmethod = EC16(folder_hdr.typeCompress);
354
+	folder->offset = (off_t) EC32(folder_hdr->coffCabStart) + offset;
355
+	folder->nblocks = EC16(folder_hdr->cCFData);
356
+	folder->cmethod = EC16(folder_hdr->typeCompress);
357 357
 
358 358
 	cli_dbgmsg("CAB: Folder record %u\n", i);
359 359
 	cli_dbgmsg("CAB: Folder offset: %u\n", (unsigned int) folder->offset);
... ...
@@ -370,16 +351,22 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
370 370
     cli_dbgmsg("CAB: Recorded folders: %u\n", folders);
371 371
 
372 372
     /* files */
373
-    if(cab->nfolders != folders && lseek(fd, EC16(hdr.coffFiles), SEEK_SET) == -1) {
374
-	cli_dbgmsg("cab_open: Can't lseek to hdr.coffFiles\n");
375
-	cab_free(cab);
376
-	return CL_EFORMAT;
373
+    if(cab->nfolders != folders) {
374
+	if(coffFiles >= rsize) {
375
+	    cli_dbgmsg("cab_open: Can't lseek to hdr.coffFiles\n");
376
+	    cab_free(cab);
377
+	    return CL_EFORMAT;
378
+	}
379
+	cur_offset = coffFiles;
377 380
     }
378 381
     for(i = 0; i < cab->nfiles; i++) {
379
-	if(cli_readn(fd, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
382
+	struct cab_file_hdr *file_hdr;
383
+
384
+	if(!(file_hdr = fmap_need_off_once(map, cur_offset, sizeof(*file_hdr)))) {
380 385
 	    cli_dbgmsg("cab_open: Can't read file %u header\n", i);
381 386
 	    break;
382 387
 	}
388
+	cur_offset += sizeof(*file_hdr);
383 389
 
384 390
 	file = (struct cab_file *) cli_calloc(1, sizeof(struct cab_file));
385 391
 	if(!file) {
... ...
@@ -389,14 +376,14 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
389 389
 	}
390 390
 
391 391
 	file->cab = cab;
392
-	file->fd = fd;
393
-	file->offset = EC32(file_hdr.uoffFolderStart);
394
-	file->length = EC32(file_hdr.cbFile);
395
-	file->attribs = EC32(file_hdr.attribs);
396
-	fidx = EC32(file_hdr.iFolder);
392
+	cab->map = map;
393
+	file->offset = EC32(file_hdr->uoffFolderStart);
394
+	file->length = EC32(file_hdr->cbFile);
395
+	file->attribs = EC32(file_hdr->attribs);
396
+	fidx = EC32(file_hdr->iFolder);
397 397
 	file->error = CL_SUCCESS;
398 398
 
399
-	file->name = cab_readstr(fd, &ret);
399
+	file->name = cab_readstr(map, &cur_offset, &ret);
400 400
 	if(ret) {
401 401
 	    free(file);
402 402
 	    continue;
... ...
@@ -460,29 +447,26 @@ int cab_open(int fd, off_t offset, struct cab_archive *cab)
460 460
     return CL_SUCCESS;
461 461
 }
462 462
 
463
-static int cab_read_block(int fd, struct cab_state *state, uint16_t resdata)
463
+static int cab_read_block(struct cab_file *file)
464 464
 {
465
-	struct cab_block_hdr block_hdr;
465
+	struct cab_block_hdr *block_hdr;
466
+	struct cab_state *state = file->cab->state;
466 467
 
467
-
468
-    if(cli_readn(fd, &block_hdr, sizeof(block_hdr)) != sizeof(block_hdr)) {
468
+    if(!(block_hdr = fmap_need_off_once(file->cab->map, file->cab->cur_offset, sizeof(*block_hdr)))) {
469 469
 	cli_dbgmsg("cab_read_block: Can't read block header\n");
470 470
 	return CL_EFORMAT; /* most likely a corrupted file */
471 471
     }
472 472
 
473
-    if(resdata && lseek(fd, (off_t) resdata, SEEK_CUR) == -1) {
474
-	cli_dbgmsg("cab_read_block: lseek failed\n");
475
-	return CL_EFORMAT; /* most likely a corrupted file */
476
-    }
477
-
478
-    state->blklen = EC16(block_hdr.cbData);
479
-    state->outlen = EC16(block_hdr.cbUncomp);
473
+    file->cab->cur_offset += sizeof(*block_hdr) + file->cab->resdata;
474
+    state->blklen = EC16(block_hdr->cbData);
475
+    state->outlen = EC16(block_hdr->cbUncomp);
480 476
 
481
-    if(cli_readn(fd, state->block, state->blklen) != state->blklen) {
477
+    if(fmap_readn(file->cab->map, state->block, file->cab->cur_offset, state->blklen) != state->blklen) {
482 478
 	cli_dbgmsg("cab_read_block: Can't read block data\n");
483 479
 	return CL_EFORMAT; /* most likely a corrupted file */
484 480
     }
485 481
 
482
+    file->cab->cur_offset += state->blklen;
486 483
     state->pt = state->end = state->block;
487 484
     state->end += state->blklen;
488 485
 
... ...
@@ -516,7 +500,7 @@ static int cab_read(struct cab_file *file, unsigned char *buffer, int bytes)
516 516
 	    if(file->cab->state->blknum++ >= file->folder->nblocks)
517 517
 		break;
518 518
 
519
-	    file->error = cab_read_block(file->fd, file->cab->state, file->cab->resdata);
519
+	    file->error = cab_read_block(file);
520 520
 	    if(file->error)
521 521
 		return -1;
522 522
 
... ...
@@ -538,9 +522,9 @@ static int cab_read(struct cab_file *file, unsigned char *buffer, int bytes)
538 538
     return file->lread = bytes - todo;
539 539
 }
540 540
 
541
-static int cab_unstore(struct cab_file *file, int bytes)
541
+static int cab_unstore(struct cab_file *file)
542 542
 {
543
-	int todo, bread;
543
+	int todo, bread, bytes = file->length;
544 544
 	unsigned char buff[4096];
545 545
 
546 546
 
... ...
@@ -559,7 +543,7 @@ static int cab_unstore(struct cab_file *file, int bytes)
559 559
 	    bread = sizeof(buff);
560 560
 
561 561
 	if((bread = cab_read(file, buff, bread)) == -1) {
562
-	    cli_dbgmsg("cab_unstore: cab_read failed for descriptor %d\n", file->fd);
562
+	    cli_dbgmsg("cab_unstore: cab_read failed\n");
563 563
 	    return file->error;
564 564
 	} else if(cli_writen(file->ofd, buff, bread) != bread) {
565 565
 	    cli_warnmsg("cab_unstore: Can't write %d bytes to descriptor %d\n", bread, file->ofd);
... ...
@@ -593,11 +577,7 @@ static int cab_unstore(struct cab_file *file, int bytes)
593 593
 	    free(file->cab->state);					\
594 594
 	    file->cab->state = NULL;					\
595 595
 	}								\
596
-	if(lseek(file->fd, file->folder->offset, SEEK_SET) == -1) {	\
597
-	    cli_dbgmsg("cab_extract: Can't lseek to %u\n", (unsigned int) file->folder->offset);							\
598
-	    close(file->ofd);						\
599
-	    return CL_EFORMAT; /* truncated file? */			\
600
-	}								\
596
+	file->cab->cur_offset = file->folder->offset;			\
601 597
 	file->cab->state = (struct cab_state *) cli_calloc(1, sizeof(struct cab_state));								\
602 598
 	if(!file->cab->state) {						\
603 599
 	    cli_errmsg("cab_extract: Can't allocate memory for internal state\n");									\
... ...
@@ -607,13 +587,13 @@ static int cab_unstore(struct cab_file *file, int bytes)
607 607
 	file->cab->state->cmethod = file->folder->cmethod;		\
608 608
 	switch(file->folder->cmethod & 0x000f) {			\
609 609
 	    case 0x0001:						\
610
-		file->cab->state->stream = (struct mszip_stream *) mszip_init(file->fd, file->ofd, 4096, 1, file, &cab_read);				\
610
+		file->cab->state->stream = (struct mszip_stream *) mszip_init(file->ofd, 4096, 1, file, &cab_read);				\
611 611
 		break;							\
612 612
 	    case 0x0002:						\
613
-		file->cab->state->stream = (struct qtm_stream *) qtm_init(file->fd, file->ofd, (int) (file->folder->cmethod >> 8) & 0x1f, 4096, file, &cab_read);									\
613
+		file->cab->state->stream = (struct qtm_stream *) qtm_init(file->ofd, (int) (file->folder->cmethod >> 8) & 0x1f, 4096, file, &cab_read);									\
614 614
 		break;							\
615 615
 	    case 0x0003:						\
616
-		file->cab->state->stream = (struct lzx_stream *) lzx_init(file->fd, file->ofd, (int) (file->folder->cmethod >> 8) & 0x1f, 0, 4096, 0, file, &cab_read);									\
616
+		file->cab->state->stream = (struct lzx_stream *) lzx_init(file->ofd, (int) (file->folder->cmethod >> 8) & 0x1f, 0, 4096, 0, file, &cab_read);									\
617 617
 	}								\
618 618
 	if((file->folder->cmethod & 0x000f) && !file->cab->state->stream) { \
619 619
 	    close(file->ofd);						\
... ...
@@ -666,7 +646,7 @@ int cab_extract(struct cab_file *file, const char *name)
666 666
 		cli_dbgmsg("cab_extract: Stored file larger than archive itself, trimming down\n");
667 667
 		file->length = file->cab->length;
668 668
 	    }
669
-	    ret = cab_unstore(file, file->length);
669
+	    ret = cab_unstore(file);
670 670
 	    break;
671 671
 
672 672
 	case 0x0001: /* MSZIP */
... ...
@@ -23,6 +23,7 @@
23 23
 
24 24
 #include <sys/types.h>
25 25
 #include "cltypes.h"
26
+#include "fmap.h"
26 27
 
27 28
 #define CAB_BLOCKMAX 65535
28 29
 #define CAB_INPUTMAX (CAB_BLOCKMAX + 6144)
... ...
@@ -31,6 +32,8 @@ struct cab_archive {
31 31
     struct cab_folder *folders, *actfol;
32 32
     struct cab_file *files;
33 33
     struct cab_state *state;
34
+    fmap_t *map;
35
+    off_t cur_offset;
34 36
     uint32_t length;
35 37
     uint16_t nfolders;
36 38
     uint16_t nfiles;
... ...
@@ -55,7 +58,6 @@ struct cab_file {
55 55
     uint32_t length;
56 56
     int error;
57 57
     int lread;
58
-    int fd;
59 58
     int ofd;
60 59
     struct cab_folder *folder;
61 60
     struct cab_file *next;
... ...
@@ -72,7 +74,7 @@ struct cab_folder {
72 72
     uint16_t nblocks;
73 73
 };
74 74
 
75
-int cab_open(int fd, off_t offset, struct cab_archive *cab);
75
+int cab_open(fmap_t *map, off_t offset, struct cab_archive *cab);
76 76
 int cab_extract(struct cab_file *file, const char *name);
77 77
 void cab_free(struct cab_archive *cab);
78 78
 
... ...
@@ -111,6 +111,14 @@ static int chm_read_data(fmap_t *map, char *dest, off_t offset, off_t len)
111 111
     return TRUE;
112 112
 }
113 113
 
114
+/* Read callback for lzx compressed data */
115
+static int chm_readn(struct cab_file *file, unsigned char *buffer, int bytes) {
116
+    int ret = fmap_readn(file->cab->map, buffer, file->cab->cur_offset, bytes);
117
+    if(ret > 0)
118
+	file->cab->cur_offset += ret;
119
+    return ret;
120
+}
121
+
114 122
 static uint64_t chm_copy_file_data(int ifd, int ofd, uint64_t len)
115 123
 {
116 124
 	unsigned char data[8192];
... ...
@@ -495,6 +503,7 @@ static int chm_decompress_stream(chm_metadata_t *metadata, const char *dirname,
495 495
 	struct lzx_stream * stream;
496 496
 	char filename[1024];
497 497
 	struct cab_file file;
498
+	struct cab_archive cab;
498 499
 	
499 500
 	snprintf(filename, 1024, "%s"PATHSEP"clamav-unchm.bin", dirname);
500 501
 	tmpfd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
... ...
@@ -555,15 +564,15 @@ static int chm_decompress_stream(chm_metadata_t *metadata, const char *dirname,
555 555
 	length &= -lzx_control.reset_interval;
556 556
 	
557 557
 	cli_dbgmsg("Compressed offset: %lu\n", (unsigned long int) lzx_content.offset);
558
-	if ((uint64_t) lseek(metadata->map->fd, lzx_content.offset, SEEK_SET) != lzx_content.offset) {
559
-		goto abort;
560
-	}
561 558
 
562 559
 	memset(&file, 0, sizeof(struct cab_file));
563 560
 	file.max_size = ctx->engine->maxfilesize;
564
-	stream = lzx_init(metadata->map->fd, tmpfd, window_bits,
561
+	file.cab = &cab;
562
+	cab.map = metadata->map;
563
+	cab.cur_offset = lzx_content.offset;
564
+	stream = lzx_init(tmpfd, window_bits,
565 565
 			lzx_control.reset_interval / LZX_FRAME_SIZE,
566
-			4096, length, &file, NULL);
566
+			4096, length, &file, chm_readn);
567 567
 	if (!stream) {
568 568
 		cli_dbgmsg("lzx_init failed\n");
569 569
 		goto abort;
... ...
@@ -365,6 +365,42 @@ extern const char *cl_retver(void);
365 365
 /* others */
366 366
 extern const char *cl_strerror(int clerror);
367 367
 
368
+/* custom data scanning */
369
+struct cl_fmap;
370
+typedef struct cl_fmap cl_fmap_t;
371
+
372
+/* handle - the handle passed to cl_fmap_open_handle, its meaning is up to the
373
+ *    callback's implementation
374
+ * buf, count, offset - read 'count' bytes starting at 'offset' into the buffer 'buf'
375
+ * Thread safety: it is guaranteed that only one callback is executing for a specific handle at
376
+ * any time, but there might be multiple callbacks executing for different
377
+ * handle at the same time.
378
+ */
379
+typedef ssize_t (*clcb_pread)(void* handle, void *buf, size_t count, off_t offset);
380
+
381
+/* Open a map for scanning custom data accessed by a handle and pread (lseek +
382
+ * read)-like interface. For example a WIN32 HANDLE.
383
+ * By default fmap will use aging to discard old data, unless you tell it not
384
+ * to.
385
+ * The handle will be passed to the callback each time.
386
+ */
387
+extern cl_fmap_t *cl_fmap_open_handle(void* handle, size_t offset, size_t len,
388
+				      clcb_pread, int use_aging);
389
+
390
+/* Open a map for scanning custom data, where the data is already in memory,
391
+ * either in the form of a buffer, a memory mapped file, etc.
392
+ * Note that the memory [start, start+len) must be the _entire_ file,
393
+ * you can't give it parts of a file and expect detection to work.
394
+ */
395
+extern cl_fmap_t *cl_fmap_open_memory(const void *start, size_t len);
396
+
397
+/* Releases resources associated with the map, you should release any resources
398
+ * you hold only after (handles, maps) calling this function */
399
+extern void cl_fmap_close(cl_fmap_t*);
400
+
401
+/* Scan custom data */
402
+extern int cl_scanmap_callback(cl_fmap_t *map, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context);
403
+
368 404
 #ifdef __cplusplus
369 405
 }
370 406
 #endif
... ...
@@ -94,17 +94,18 @@ static void sanitname(char *name)
94 94
     }
95 95
 }
96 96
 
97
-int cli_scancpio_old(int fd, cli_ctx *ctx)
97
+int cli_scancpio_old(cli_ctx *ctx)
98 98
 {
99 99
 	struct cpio_hdr_old hdr_old;
100 100
 	char name[513];
101 101
 	unsigned int file = 0, trailer = 0;
102 102
 	uint32_t filesize, namesize, hdr_namesize;
103 103
 	int ret, conv;
104
-	off_t pos;
104
+	off_t pos = 0;
105 105
 
106 106
 
107
-    while(read(fd, &hdr_old, sizeof(hdr_old)) == sizeof(hdr_old)) {
107
+    while(fmap_readn(*ctx->fmap, &hdr_old, pos, sizeof(hdr_old)) == sizeof(hdr_old)) {
108
+	pos += sizeof(hdr_old);
108 109
 	if(!hdr_old.magic && trailer)
109 110
 	    return CL_SUCCESS;
110 111
 
... ...
@@ -122,10 +123,11 @@ int cli_scancpio_old(int fd, cli_ctx *ctx)
122 122
 	if(hdr_old.namesize) {
123 123
 	    hdr_namesize = EC16(hdr_old.namesize, conv);
124 124
 	    namesize = MIN(sizeof(name), hdr_namesize);
125
-	    if(read(fd, name, namesize) != namesize) {
125
+	    if (fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
126 126
 		cli_dbgmsg("cli_scancpio_old: Can't read file name\n");
127 127
 		return CL_EFORMAT;
128 128
 	    }
129
+	    pos += namesize;
129 130
 	    name[namesize - 1] = 0;
130 131
 	    sanitname(name);
131 132
 	    cli_dbgmsg("CPIO: Name: %s\n", name);
... ...
@@ -135,9 +137,9 @@ int cli_scancpio_old(int fd, cli_ctx *ctx)
135 135
 	    if(namesize < hdr_namesize) {
136 136
 		if(hdr_namesize % 2)
137 137
 		    hdr_namesize++;
138
-		lseek(fd, hdr_namesize - namesize, SEEK_CUR);
138
+		pos += hdr_namesize - namesize;
139 139
 	    } else if(hdr_namesize % 2)
140
-		lseek(fd, 1, SEEK_CUR);
140
+		pos++;
141 141
 	}
142 142
 	filesize = (uint32_t) (EC16(hdr_old.filesize[0], conv) << 16 | EC16(hdr_old.filesize[1], conv));
143 143
 	cli_dbgmsg("CPIO: Filesize: %u\n", filesize);
... ...
@@ -147,7 +149,6 @@ int cli_scancpio_old(int fd, cli_ctx *ctx)
147 147
 	if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS)
148 148
 	    return CL_VIRUS;
149 149
 
150
-	pos = lseek(fd, 0, SEEK_CUR);
151 150
 
152 151
 	if((EC16(hdr_old.mode, conv) & 0170000) != 0100000) {
153 152
 	    cli_dbgmsg("CPIO: Not a regular file, skipping\n");
... ...
@@ -156,7 +157,7 @@ int cli_scancpio_old(int fd, cli_ctx *ctx)
156 156
 	    if(ret == CL_EMAXFILES) {
157 157
 		return ret;
158 158
 	    } else if(ret == CL_SUCCESS) {
159
-		ret = cli_dumpscan(fd, 0, filesize, ctx);
159
+		ret = cli_map_scandesc(*ctx->fmap, pos, filesize, ctx);
160 160
 		if(ret == CL_VIRUS)
161 161
 		    return ret;
162 162
 	    }
... ...
@@ -164,24 +165,24 @@ int cli_scancpio_old(int fd, cli_ctx *ctx)
164 164
 	if(filesize % 2)
165 165
 	    filesize++;
166 166
 
167
-	lseek(fd, pos + filesize, SEEK_SET);
167
+	pos += filesize;
168 168
     }
169 169
 
170 170
     return CL_CLEAN;
171 171
 }
172 172
 
173
-int cli_scancpio_odc(int fd, cli_ctx *ctx)
173
+int cli_scancpio_odc(cli_ctx *ctx)
174 174
 {
175 175
 	struct cpio_hdr_odc hdr_odc;
176 176
 	char name[513], buff[12];
177 177
 	unsigned int file = 0, trailer = 0;
178 178
 	uint32_t filesize, namesize, hdr_namesize;
179 179
 	int ret;
180
-	off_t pos;
180
+	off_t pos = 0;
181 181
 
182 182
 
183
-    while(read(fd, &hdr_odc, sizeof(hdr_odc)) == sizeof(hdr_odc)) {
184
-
183
+    while(fmap_readn(*ctx->fmap, &hdr_odc, pos, sizeof(hdr_odc)) == sizeof(hdr_odc)) {
184
+	pos += sizeof(hdr_odc);
185 185
 	if(!hdr_odc.magic[0] && trailer)
186 186
 	    return CL_SUCCESS;
187 187
 
... ...
@@ -200,10 +201,11 @@ int cli_scancpio_odc(int fd, cli_ctx *ctx)
200 200
 	}
201 201
 	if(hdr_namesize) {
202 202
 	    namesize = MIN(sizeof(name), hdr_namesize);
203
-	    if(read(fd, name, namesize) != namesize) {
203
+	    if (fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
204 204
 		cli_dbgmsg("cli_scancpio_odc: Can't read file name\n");
205 205
 		return CL_EFORMAT;
206 206
 	    }
207
+	    pos += namesize;
207 208
 	    name[namesize - 1] = 0;
208 209
 	    sanitname(name);
209 210
 	    cli_dbgmsg("CPIO: Name: %s\n", name);
... ...
@@ -211,7 +213,7 @@ int cli_scancpio_odc(int fd, cli_ctx *ctx)
211 211
 		trailer = 1;
212 212
 
213 213
 	    if(namesize < hdr_namesize)
214
-		lseek(fd, hdr_namesize - namesize, SEEK_CUR);
214
+		pos += hdr_namesize - namesize;
215 215
 	}
216 216
 
217 217
 	strncpy(buff, hdr_odc.filesize, 11);
... ...
@@ -227,35 +229,34 @@ int cli_scancpio_odc(int fd, cli_ctx *ctx)
227 227
 	if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS)
228 228
 	    return CL_VIRUS;
229 229
 
230
-	pos = lseek(fd, 0, SEEK_CUR);
231 230
 
232 231
 	ret = cli_checklimits("cli_scancpio_odc", ctx, filesize, 0, 0);
233 232
 	if(ret == CL_EMAXFILES) {
234 233
 	    return ret;
235 234
 	} else if(ret == CL_SUCCESS) {
236
-	    ret = cli_dumpscan(fd, 0, filesize, ctx);
235
+	    ret = cli_map_scandesc(*ctx->fmap, pos, filesize, ctx);
237 236
 	    if(ret == CL_VIRUS)
238 237
 		return ret;
239 238
 	}
240 239
 
241
-	lseek(fd, pos + filesize, SEEK_SET);
240
+	pos += filesize;
242 241
     }
243 242
 
244 243
     return CL_CLEAN;
245 244
 }
246 245
 
247
-int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc)
246
+int cli_scancpio_newc(cli_ctx *ctx, int crc)
248 247
 {
249 248
 	struct cpio_hdr_newc hdr_newc;
250 249
 	char name[513], buff[9];
251 250
 	unsigned int file = 0, trailer = 0;
252 251
 	uint32_t filesize, namesize, hdr_namesize, pad;
253 252
 	int ret;
254
-	off_t pos;
255
-
253
+	off_t pos = 0;
256 254
 
257
-    while(read(fd, &hdr_newc, sizeof(hdr_newc)) == sizeof(hdr_newc)) {
258 255
 
256
+    while(fmap_readn(*ctx->fmap, &hdr_newc, pos, sizeof(hdr_newc)) == sizeof(hdr_newc)) {
257
+	pos += sizeof(hdr_newc);
259 258
 	if(!hdr_newc.magic[0] && trailer)
260 259
 	    return CL_SUCCESS;
261 260
 
... ...
@@ -274,10 +275,11 @@ int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc)
274 274
 	}
275 275
 	if(hdr_namesize) {
276 276
 	    namesize = MIN(sizeof(name), hdr_namesize);
277
-	    if(read(fd, name, namesize) != namesize) {
277
+	    if (fmap_readn(*ctx->fmap, &name, pos, namesize) != namesize) {
278 278
 		cli_dbgmsg("cli_scancpio_newc: Can't read file name\n");
279 279
 		return CL_EFORMAT;
280 280
 	    }
281
+	    pos += namesize;
281 282
 	    name[namesize - 1] = 0;
282 283
 	    sanitname(name);
283 284
 	    cli_dbgmsg("CPIO: Name: %s\n", name);
... ...
@@ -288,9 +290,9 @@ int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc)
288 288
 	    if(namesize < hdr_namesize) {
289 289
 		if(pad)
290 290
 		    hdr_namesize += pad;
291
-		lseek(fd, hdr_namesize - namesize, SEEK_CUR);
291
+		pos += hdr_namesize - namesize;
292 292
 	    } else if(pad)
293
-		lseek(fd, pad, SEEK_CUR);
293
+		pos += pad;
294 294
 	}
295 295
 
296 296
 	strncpy(buff, hdr_newc.filesize, 8);
... ...
@@ -306,13 +308,12 @@ int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc)
306 306
 	if(cli_matchmeta(ctx, name, filesize, filesize, 0, file, 0, NULL) == CL_VIRUS)
307 307
 	    return CL_VIRUS;
308 308
 
309
-	pos = lseek(fd, 0, SEEK_CUR);
310 309
 
311 310
 	ret = cli_checklimits("cli_scancpio_newc", ctx, filesize, 0, 0);
312 311
 	if(ret == CL_EMAXFILES) {
313 312
 	    return ret;
314 313
 	} else if(ret == CL_SUCCESS) {
315
-	    ret = cli_dumpscan(fd, 0, filesize, ctx);
314
+	    ret = cli_map_scandesc(*ctx->fmap, pos, filesize, ctx);
316 315
 	    if(ret == CL_VIRUS)
317 316
 		return ret;
318 317
 	}
... ...
@@ -320,7 +321,7 @@ int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc)
320 320
 	if((pad = filesize % 4))
321 321
 	    filesize += (4 - pad);
322 322
 
323
-	lseek(fd, pos + filesize, SEEK_SET);
323
+	pos += filesize;
324 324
     }
325 325
 
326 326
     return CL_CLEAN;
... ...
@@ -23,8 +23,8 @@
23 23
 
24 24
 #include "others.h"
25 25
 
26
-int cli_scancpio_old(int fd, cli_ctx *ctx);
27
-int cli_scancpio_odc(int fd, cli_ctx *ctx);
28
-int cli_scancpio_newc(int fd, cli_ctx *ctx, int crc);
26
+int cli_scancpio_old(cli_ctx *ctx);
27
+int cli_scancpio_odc(cli_ctx *ctx);
28
+int cli_scancpio_newc(cli_ctx *ctx, int crc);
29 29
 
30 30
 #endif
... ...
@@ -262,7 +262,7 @@ int crtmgr_verify_crt(crtmgr *m, cli_crt *x509) {
262 262
     return 1;
263 263
 }
264 264
 
265
-int crtmgr_verify_pkcs7(crtmgr *m, uint8_t *issuer, void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash) {
265
+int crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash) {
266 266
     cli_crt *i;
267 267
     mp_int sig;
268 268
     int ret;
... ...
@@ -57,7 +57,7 @@ int crtmgr_add(crtmgr *m, cli_crt *x509);
57 57
 cli_crt *crtmgr_lookup(crtmgr *m, cli_crt *x509);
58 58
 void crtmgr_del(crtmgr *m, cli_crt *x509);
59 59
 int crtmgr_verify_crt(crtmgr *m, cli_crt *x509);
60
-int crtmgr_verify_pkcs7(crtmgr *m, uint8_t *issuer, void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash);
60
+int crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash);
61 61
 int crtmgr_add_roots(crtmgr *m);
62 62
 
63 63
 
... ...
@@ -96,6 +96,7 @@ static const struct ftmap_s {
96 96
     { "CL_TYPE_AUTOIT",		CL_TYPE_AUTOIT		},
97 97
     { "CL_TYPE_ISHIELD_MSI",	CL_TYPE_ISHIELD_MSI	},
98 98
     { "CL_TYPE_7Z",		CL_TYPE_7Z		},
99
+    { "CL_TYPE_7ZSFX",		CL_TYPE_7ZSFX		},
99 100
     { "CL_TYPE_SWF",		CL_TYPE_SWF		},
100 101
     { "CL_TYPE_ISO9660",	CL_TYPE_ISO9660		},
101 102
     { NULL,			CL_TYPE_IGNORED		}
... ...
@@ -80,6 +80,7 @@ typedef enum {
80 80
     CL_TYPE_SFX, /* foo SFX marker */
81 81
     CL_TYPE_ZIPSFX, /* on the fly */
82 82
     CL_TYPE_RARSFX, /* on the fly */
83
+    CL_TYPE_7ZSFX,
83 84
     CL_TYPE_CABSFX,
84 85
     CL_TYPE_ARJSFX,
85 86
     CL_TYPE_NULSFT, /* on the fly */
... ...
@@ -56,7 +56,6 @@ static const char *ftypes_int[] = {
56 56
   "0:0:48692e20546869732069732074686520716d61696c2d73656e64:Qmail bounce:CL_TYPE_ANY:CL_TYPE_MAIL",
57 57
   "0:0:494433:MP3:CL_TYPE_ANY:CL_TYPE_IGNORED",
58 58
   "0:0:49545346:MS CHM:CL_TYPE_ANY:CL_TYPE_MSCHM",
59
-  "0:0:4d534346:MS CAB:CL_TYPE_ANY:CL_TYPE_MSCAB",
60 59
   "0:0:4d5a:MS-EXE/DLL:CL_TYPE_ANY:CL_TYPE_MSEXE",
61 60
   "0:0:4d6573736167652d49443a20:Mail:CL_TYPE_ANY:CL_TYPE_MAIL",
62 61
   "0:0:4d6573736167652d49643a20:Mail:CL_TYPE_ANY:CL_TYPE_MAIL",
... ...
@@ -117,7 +116,6 @@ static const char *ftypes_int[] = {
117 117
   "1:*:3c6f626a656374:HTML data:CL_TYPE_ANY:CL_TYPE_HTML",
118 118
   "1:*:3c736372697074:HTML data:CL_TYPE_ANY:CL_TYPE_HTML",
119 119
   "1:*:3c7461626c65:HTML data:CL_TYPE_ANY:CL_TYPE_HTML",
120
-  "1:*:4d534346:CAB-SFX:CL_TYPE_ANY:CL_TYPE_CABSFX",
121 120
   "1:*:4d5a{60-300}50450000:PE:CL_TYPE_ANY:CL_TYPE_MSEXE",
122 121
   "1:*:504b0304:ZIP-SFX:CL_TYPE_ANY:CL_TYPE_ZIPSFX",
123 122
   "1:*:526172211a0700:RAR-SFX:CL_TYPE_ANY:CL_TYPE_RARSFX",
... ...
@@ -151,7 +149,7 @@ static const char *ftypes_int[] = {
151 151
   "1:*:496e7374616c6c536869656c6400{292}0600000000000000????????????????0000000001:ISHIELD-MSI:CL_TYPE_ANY:CL_TYPE_ISHIELD_MSI:45",
152 152
   "0:0:255044462d:PDF document:CL_TYPE_ANY:CL_TYPE_PDF:30:53",
153 153
   "1:*:255044462d??2e*737461727478726566*2525454f46:PDF:CL_TYPE_ANY:CL_TYPE_PDF:54:54",
154
-  "1:*:255044462d??2e:PDF:CL_TYPE_ANY:CL_TYPE_PDF:30:53",
154
+  "1:*:377abcaf271c:7zip-SFX:CL_TYPE_ANY:CL_TYPE_7ZSFX",
155 155
   "1:*:257064662d??2e*737461727478726566*2525454f46:PDF:CL_TYPE_ANY:CL_TYPE_PDF:54:54",
156 156
   "1:*:257064662d??2e:PDF:CL_TYPE_ANY:CL_TYPE_PDF:30:53",
157 157
   "1:0:255044462d*737461727478726566*2525454f46:PDF document:CL_TYPE_ANY:CL_TYPE_PDF:54:54",
... ...
@@ -164,7 +162,10 @@ static const char *ftypes_int[] = {
164 164
   "0:0:377f0683002de218:SQLite WAL:CL_TYPE_ANY:CL_TYPE_IGNORED",
165 165
   "0:0:53514c69746520666f726d6174203300:SQLite database:CL_TYPE_ANY:CL_TYPE_IGNORED",
166 166
   "0:0:d9d505f920a163d7:SQLite journal:CL_TYPE_ANY:CL_TYPE_IGNORED",
167
-  "0:0:ffd9ffd8:JPEG (bad header):CL_TYPE_ANY:CL_TYPE_GRAPHICS:70",
167
+  "0:0:435753:SWF (compressed):CL_TYPE_ANY:CL_TYPE_SWF:71",
168
+  "0:0:465753:SWF (uncompressed):CL_TYPE_ANY:CL_TYPE_SWF:71",
169
+  "0:0:4d53434600000000:MS CAB:CL_TYPE_ANY:CL_TYPE_MSCAB",
170
+  "1:*:4d53434600000000:CAB-SFX:CL_TYPE_ANY:CL_TYPE_CABSFX",
168 171
   "1:*:014344303031{2043-2443}4344303031:ISO9660:CL_TYPE_ANY:CL_TYPE_ISO9660:71",
169 172
   NULL
170 173
 };
... ...
@@ -50,6 +50,114 @@ static inline unsigned int fmap_which_page(fmap_t *m, size_t at);
50 50
 
51 51
 #ifndef _WIN32
52 52
 /* vvvvv POSIX STUFF BELOW vvvvv */
53
+static ssize_t pread_cb(void *handle, void *buf, size_t count, off_t offset);
54
+
55
+/* pread proto here in order to avoid the use of XOPEN and BSD_SOURCE
56
+   which may in turn prevent some mmap constants to be defined */
57
+ssize_t pread(int fd, void *buf, size_t count, off_t offset);
58
+
59
+fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty) {
60
+    unsigned int pages, mapsz, hdrsz;
61
+    unsigned short dumb = 1;
62
+    int pgsz = cli_getpagesize();
63
+    struct stat st;
64
+    fmap_t *m;
65
+    void *handle = (void*)(ssize_t)fd;
66
+
67
+    *empty = 0;
68
+    if(fstat(fd, &st)) {
69
+	cli_warnmsg("fmap: fstat failed\n");
70
+	return NULL;
71
+    }
72
+
73
+    if(!len) len = st.st_size - offset; /* bound checked later */
74
+    if(!len) {
75
+	cli_dbgmsg("fmap: attempted void mapping\n");
76
+	*empty = 1;
77
+	return NULL;
78
+    }
79
+    if(!CLI_ISCONTAINED(0, st.st_size, offset, len)) {
80
+	cli_warnmsg("fmap: attempted oof mapping\n");
81
+	return NULL;
82
+    }
83
+    m = cl_fmap_open_handle((void*)(ssize_t)fd, offset, len, pread_cb, 1);
84
+    if (!m)
85
+	return NULL;
86
+    m->mtime = st.st_mtime;
87
+    m->handle_is_fd = 1;
88
+    return m;
89
+}
90
+#else
91
+/* vvvvv WIN32 STUFF BELOW vvvvv */
92
+static void unmap_win32(fmap_t *m) { /* WIN32 */
93
+    UnmapViewOfFile(m->data);
94
+    CloseHandle(m->mh);
95
+    free((void *)m);
96
+}
97
+
98
+fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty) { /* WIN32 */
99
+    unsigned int pages, mapsz, hdrsz;
100
+    int pgsz = cli_getpagesize();
101
+    struct stat st;
102
+    fmap_t *m;
103
+    const void *data;
104
+    HANDLE fh;
105
+    HANDLE mh;
106
+
107
+    *empty = 0;
108
+    if(fstat(fd, &st)) {
109
+	cli_warnmsg("fmap: fstat failed\n");
110
+	return NULL;
111
+    }
112
+    if(offset < 0 || offset != fmap_align_to(offset, pgsz)) {
113
+	cli_warnmsg("fmap: attempted mapping with unaligned offset\n");
114
+	return NULL;
115
+    }
116
+    if(!len) len = st.st_size - offset; /* bound checked later */
117
+    if(!len) {
118
+	cli_dbgmsg("fmap: attempted void mapping\n");
119
+	*empty = 1;
120
+	return NULL;
121
+    }
122
+    if(!CLI_ISCONTAINED(0, st.st_size, offset, len)) {
123
+	cli_warnmsg("fmap: attempted oof mapping\n");
124
+	return NULL;
125
+    }
126
+
127
+    pages = fmap_align_items(len, pgsz);
128
+    hdrsz = fmap_align_to(sizeof(fmap_t), pgsz);
129
+
130
+    if((fh = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) {
131
+	cli_errmsg("fmap: cannot get a valid handle for descriptor %d\n", fd);
132
+	return NULL;
133
+    }
134
+    if(!(mh = CreateFileMapping(m->fh, NULL, PAGE_READONLY, (DWORD)((len>>31)>>1), (DWORD)len, NULL))) {
135
+	cli_errmsg("fmap: cannot create a map of descriptor %d\n", fd);
136
+	CloseHandle(fh);
137
+	return NULL;
138
+    }
139
+    if(!(data = MapViewOfFile(m->mh, FILE_MAP_READ, (DWORD)((offset>>31)>>1), (DWORD)(offset), len))) {
140
+	cli_errmsg("fmap: cannot map file descriptor %d\n", fd);
141
+	CloseHandle(mh);
142
+	CloseHandle(fh);
143
+	return NULL;
144
+    }
145
+    if(!(m = cl_fmap_open_memory(data, len))) {
146
+	cli_errmsg("fmap: canot allocate fmap_t\n", fd);
147
+	CloseHandle(mh);
148
+	CloseHandle(fh);
149
+	return NULL;
150
+    }
151
+    m->handle = (void*)(ssize_t)fd;
152
+    m->handle_is_fd = 1;
153
+    m->fh = fh;
154
+    m->mh = mh;
155
+    m->unmap = unmap_win32;
156
+    return m;
157
+}
158
+#endif /* _WIN32 */
159
+
160
+/* vvvvv SHARED STUFF BELOW vvvvv */
53 161
 
54 162
 #define FM_MASK_COUNT 0x3fffffff
55 163
 #define FM_MASK_PAGED 0x40000000
... ...
@@ -88,34 +196,29 @@ pthread_mutex_t fmap_mutex = PTHREAD_MUTEX_INITIALIZER;
88 88
 
89 89
 #define fmap_bitmap (&m->placeholder_for_bitmap)
90 90
 
91
-/* pread proto here in order to avoid the use of XOPEN and BSD_SOURCE
92
-   which may in turn prevent some mmap constants to be defined */
93
-ssize_t pread(int fd, void *buf, size_t count, off_t offset);
94
-
91
+static const void *handle_need(fmap_t *m, size_t at, size_t len, int lock);
92
+static void handle_unneed_off(fmap_t *m, size_t at, size_t len);
93
+static const void *handle_need_offstr(fmap_t *m, size_t at, size_t len_hint);
94
+static const void *handle_gets(fmap_t *m, char *dst, size_t *at, size_t max_len);
95
+static void unmap_mmap(fmap_t *m);
96
+static void unmap_malloc(fmap_t *m);
95 97
 
96
-fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty) {
98
+extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len,
99
+				      clcb_pread pread_cb, int use_aging)
100
+{
97 101
     unsigned int pages, mapsz, hdrsz;
98
-    unsigned short dumb = 1;
102
+    cl_fmap_t *m;
99 103
     int pgsz = cli_getpagesize();
100
-    struct stat st;
101
-    fmap_t *m;
102 104
 
103
-    *empty = 0;
104
-    if(fstat(fd, &st)) {
105
-	cli_warnmsg("fmap: fstat failed\n");
106
-	return NULL;
107
-    }
108 105
     if(offset < 0 || offset != fmap_align_to(offset, pgsz)) {
109 106
 	cli_warnmsg("fmap: attempted mapping with unaligned offset\n");
110 107
 	return NULL;
111 108
     }
112
-    if(!len) len = st.st_size - offset; /* bound checked later */
113 109
     if(!len) {
114 110
 	cli_dbgmsg("fmap: attempted void mapping\n");
115
-	*empty = 1;
116 111
 	return NULL;
117 112
     }
118
-    if(!CLI_ISCONTAINED(0, st.st_size, offset, len)) {
113
+    if (offset >= len) {
119 114
 	cli_warnmsg("fmap: attempted oof mapping\n");
120 115
 	return NULL;
121 116
     }
... ...
@@ -123,44 +226,60 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty) {
123 123
     pages = fmap_align_items(len, pgsz);
124 124
     hdrsz = fmap_align_to(sizeof(fmap_t) + (pages-1) * sizeof(uint32_t), pgsz); /* fmap_t includes 1 bitmap slot, hence (pages-1) */
125 125
     mapsz = pages * pgsz + hdrsz;
126
-    fmap_lock;
126
+
127
+#ifndef ANONYMOUS_MAP
128
+    use_aging = 0;
129
+#endif
127 130
 #ifdef ANONYMOUS_MAP
128
-    if ((m = (fmap_t *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|/*FIXME: MAP_POPULATE is ~8% faster but more memory intensive */ANONYMOUS_MAP, -1, 0)) == MAP_FAILED) {
129
-	m = NULL;
130
-    } else {
131
-	dumb = 0;
131
+    if (use_aging) {
132
+	fmap_lock;
133
+	if ((m = (fmap_t *)mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE|/*FIXME: MAP_POPULATE is ~8% faster but more memory intensive */ANONYMOUS_MAP, -1, 0)) == MAP_FAILED) {
134
+	    m = NULL;
135
+	} else {
132 136
 #if HAVE_MADVISE
133
-	madvise((void *)m, mapsz, MADV_RANDOM|MADV_DONTFORK);
137
+	    madvise((void *)m, mapsz, MADV_RANDOM|MADV_DONTFORK);
134 138
 #endif /* madvise */
139
+	    /* fault the header while we still have the lock - we DO context switch here a lot here :@ */
140
+	    memset(fmap_bitmap, 0, sizeof(uint32_t) * pages);
141
+	}
142
+	fmap_unlock;
135 143
     }
136
-#else /* ! ANONYMOUS_MAP */
137
-    m = (fmap_t *)cli_malloc(mapsz);
138 144
 #endif /* ANONYMOUS_MAP */
145
+    if (!use_aging) {
146
+	m = (fmap_t *)cli_malloc(mapsz);
147
+	memset(m, 0, hdrsz);
148
+    }
139 149
     if(!m) {
140 150
 	cli_warnmsg("fmap: map allocation failed\n");
141
-	fmap_unlock;
142 151
 	return NULL;
143 152
     }
144
-    /* fault the header while we still have the lock - we DO context switch here a lot here :@ */
145
-    memset(fmap_bitmap, 0, sizeof(uint32_t) * pages);
146
-    fmap_unlock;
147
-    m->fd = fd;
148
-    m->dumb = dumb;
149
-    m->mtime = st.st_mtime;
153
+    m->handle = handle;
154
+    m->pread_cb = pread_cb;
155
+    m->aging = use_aging;
150 156
     m->offset = offset;
151
-    m->len = len;
157
+    m->len = len;/* m->nested_offset + m->len = m->real_len */
158
+    m->real_len = len;
152 159
     m->pages = pages;
153 160
     m->hdrsz = hdrsz;
154 161
     m->pgsz = pgsz;
155 162
     m->paged = 0;
156 163
     m->dont_cache_flag = 0;
164
+    m->unmap = use_aging ? unmap_mmap : unmap_malloc;
165
+    m->need = handle_need;
166
+    m->need_offstr = handle_need_offstr;
167
+    m->gets = handle_gets;
168
+    m->unneed_off = handle_unneed_off;
157 169
     return m;
158 170
 }
159 171
 
172
+static ssize_t pread_cb(void *handle, void *buf, size_t count, off_t offset)
173
+{
174
+    return pread((int)(ssize_t)handle, buf, count, offset);
175
+}
160 176
 
161 177
 static void fmap_aging(fmap_t *m) {
162 178
 #ifdef ANONYMOUS_MAP
163
-    if(m->dumb) return;
179
+    if(!m->aging) return;
164 180
     if(m->paged * m->pgsz > UNPAGE_THRSHLD_HI) { /* we alloc'd too much */
165 181
 	unsigned int i, avail = 0, freeme[2048], maxavail = MIN(sizeof(freeme)/sizeof(*freeme), m->paged - UNPAGE_THRSHLD_LO / m->pgsz) - 1;
166 182
 
... ...
@@ -234,7 +353,7 @@ static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count,
234 234
 
235 235
     fmap_lock;
236 236
     for(i=0; i<count; i++) { /* prefault */
237
-    	/* Not worth checking if the page is already paged, just ping each */
237
+	/* Not worth checking if the page is already paged, just ping each */
238 238
 	/* Also not worth reusing the loop below */
239 239
 	volatile char faultme;
240 240
 	faultme = ((char *)m)[(first_page+i) * m->pgsz + m->hdrsz];
... ...
@@ -278,27 +397,31 @@ static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count,
278 278
 
279 279
 	if(force_read) {
280 280
 	    /* we have some pending reads to perform */
281
-	    unsigned int j;
282
-	    for(j=first_page; j<page; j++) {
283
-		if(fmap_bitmap[j] & FM_MASK_SEEN) {
284
-		    /* page we've seen before: check mtime */
285
-		    struct stat st;
286
-		    if(fstat(m->fd, &st)) {
287
-			cli_warnmsg("fmap_readpage: fstat failed\n");
288
-			return 1;
289
-		    }
290
-		    if(m->mtime != st.st_mtime) {
291
-			cli_warnmsg("fmap_readpage: file changed as we read it\n");
292
-			return 1;
281
+	    if (m->handle_is_fd) {
282
+		unsigned int j;
283
+		int _fd = (int)(ssize_t)m->handle;
284
+		for(j=first_page; j<page; j++) {
285
+		    if(fmap_bitmap[j] & FM_MASK_SEEN) {
286
+			/* page we've seen before: check mtime */
287
+			struct stat st;
288
+			char err[256];
289
+			if(fstat(_fd, &st)) {
290
+			    cli_warnmsg("fmap_readpage: fstat failed: %s\n", cli_strerror(errno, err, sizeof(err)));
291
+			    return 1;
292
+			}
293
+			if(m->mtime != st.st_mtime) {
294
+			    cli_warnmsg("fmap_readpage: file changed as we read it\n");
295
+			    return 1;
296
+			}
297
+			break;
293 298
 		    }
294
-		    break;
295 299
 		}
296 300
 	    }
297 301
 
298 302
 	    eintr_off = 0;
299 303
 	    while(readsz) {
300 304
 		ssize_t got;
301
-		got=pread(m->fd, pptr, readsz, eintr_off + m->offset + first_page * m->pgsz);
305
+		got=m->pread_cb(m->handle, pptr, readsz, eintr_off + m->offset + first_page * m->pgsz);
302 306
 
303 307
 		if(got < 0 && errno == EINTR)
304 308
 		    continue;
... ...
@@ -329,8 +452,8 @@ static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count,
329 329
 	    pptr = (char *)m + page * m->pgsz + m->hdrsz;
330 330
 	    first_page = page;
331 331
 	}
332
-	if((page == m->pages - 1) && (m->len % m->pgsz))
333
-	    readsz += m->len % m->pgsz;
332
+	if((page == m->pages - 1) && (m->real_len % m->pgsz))
333
+	    readsz += m->real_len % m->pgsz;
334 334
 	else
335 335
 	    readsz += m->pgsz;
336 336
 	if(lock) /* lock requested: set paged, lock page and set lock count to 1 */
... ...
@@ -343,14 +466,16 @@ static int fmap_readpage(fmap_t *m, unsigned int first_page, unsigned int count,
343 343
 }
344 344
 
345 345
 
346
-static void *fmap_need(fmap_t *m, size_t at, size_t len, int lock) {
346
+static const void *handle_need(fmap_t *m, size_t at, size_t len, int lock) {
347 347
     unsigned int first_page, last_page, lock_count;
348 348
     char *ret;
349 349
 
350 350
     if(!len)
351 351
 	return NULL;
352 352
 
353
-    if(!CLI_ISCONTAINED(0, m->len, at, len))
353
+    at += m->nested_offset;
354
+
355
+    if(!CLI_ISCONTAINED(0, m->real_len, at, len))
354 356
 	return NULL;
355 357
 
356 358
     fmap_aging(m);
... ...
@@ -371,23 +496,6 @@ static void *fmap_need(fmap_t *m, size_t at, size_t len, int lock) {
371 371
     return (void *)ret;
372 372
 }
373 373
 
374
-void *fmap_need_off(fmap_t *m, size_t at, size_t len) {
375
-    return fmap_need(m, at, len, 1);
376
-}
377
-void *fmap_need_off_once(fmap_t *m, size_t at, size_t len) {
378
-    return fmap_need(m, at, len, 0);
379
-}
380
-void *fmap_need_ptr(fmap_t *m, void *ptr, size_t len) {
381
-    return fmap_need_off(m, (char *)ptr - (char *)m - m->hdrsz, len);
382
-}
383
-void *fmap_need_ptr_once(fmap_t *m, void *ptr, size_t len) {
384
-    return fmap_need_off_once(m, (char *)ptr - (char *)m - m->hdrsz, len);
385
-}
386
-void *fmap_need_str(fmap_t *m, void *ptr, size_t len_hint) {
387
-    size_t at = (char *)ptr - (char *)m - m->hdrsz;
388
-    return fmap_need_offstr(m, at, len_hint);
389
-}
390
-
391 374
 static void fmap_unneed_page(fmap_t *m, unsigned int page) {
392 375
     uint32_t s = fmap_bitmap[page];
393 376
 
... ...
@@ -406,15 +514,15 @@ static void fmap_unneed_page(fmap_t *m, unsigned int page) {
406 406
     return;
407 407
 }
408 408
 
409
-void fmap_unneed_off(fmap_t *m, size_t at, size_t len) {
409
+static void handle_unneed_off(fmap_t *m, size_t at, size_t len) {
410 410
     unsigned int i, first_page, last_page;
411
-    if(m->dumb) return;
411
+    if(!m->aging) return;
412 412
     if(!len) {
413 413
 	cli_warnmsg("fmap_unneed: attempted void unneed\n");
414 414
 	return;
415 415
     }
416 416
 
417
-    if(!CLI_ISCONTAINED(0, m->len, at, len)) {
417
+    if(!CLI_ISCONTAINED(0, m->real_len, at, len)) {
418 418
 	cli_warnmsg("fmap: attempted oof unneed\n");
419 419
 	return;
420 420
     }
... ...
@@ -427,30 +535,28 @@ void fmap_unneed_off(fmap_t *m, size_t at, size_t len) {
427 427
     }
428 428
 }
429 429
 
430
-void fmap_unneed_ptr(fmap_t *m, void *ptr, size_t len) {
431
-    fmap_unneed_off(m, (char *)ptr - (char *)m - m->hdrsz, len);
432
-}
433
-
434
-void funmap(fmap_t *m) {
430
+static void unmap_mmap(fmap_t *m)
431
+{
435 432
 #ifdef ANONYMOUS_MAP
436
-    if(!m->dumb) {
437
-	size_t len = m->pages * m->pgsz + m->hdrsz;
438
-	fmap_lock;
439
-	munmap((void *)m, len);
440
-	fmap_unlock;
441
-    } else
433
+    size_t len = m->pages * m->pgsz + m->hdrsz;
434
+    fmap_lock;
435
+    munmap((void *)m, len);
436
+    fmap_unlock;
442 437
 #endif
443
-	free((void *)m);
444 438
 }
445 439
 
446
-void *fmap_need_offstr(fmap_t *m, size_t at, size_t len_hint) {
440
+static void unmap_malloc(fmap_t *m) {
441
+    free((void *)m);
442
+}
443
+
444
+static const void *handle_need_offstr(fmap_t *m, size_t at, size_t len_hint) {
447 445
     unsigned int i, first_page, last_page;
448 446
     void *ptr = (void *)((char *)m + m->hdrsz + at);
449 447
 
450
-    if(!len_hint || len_hint > m->len - at)
451
-	len_hint = m->len - at;
448
+    if(!len_hint || len_hint > m->real_len - at)
449
+	len_hint = m->real_len - at;
452 450
 
453
-    if(!CLI_ISCONTAINED(0, m->len, at, len_hint))
451
+    if(!CLI_ISCONTAINED(0, m->real_len, at, len_hint))
454 452
 	return NULL;
455 453
 
456 454
     fmap_aging(m);
... ...
@@ -482,13 +588,12 @@ void *fmap_need_offstr(fmap_t *m, size_t at, size_t len_hint) {
482 482
     return NULL;
483 483
 }
484 484
 
485
-
486
-void *fmap_gets(fmap_t *m, char *dst, size_t *at, size_t max_len) {
485
+static const void *handle_gets(fmap_t *m, char *dst, size_t *at, size_t max_len) {
487 486
     unsigned int i, first_page, last_page;
488 487
     char *src = (void *)((char *)m + m->hdrsz + *at), *endptr = NULL;
489
-    size_t len = MIN(max_len-1, m->len - *at), fullen = len;
488
+    size_t len = MIN(max_len-1, m->real_len - *at), fullen = len;
490 489
 
491
-    if(!len || !CLI_ISCONTAINED(0, m->len, *at, len))
490
+    if(!len || !CLI_ISCONTAINED(0, m->real_len, *at, len))
492 491
 	return NULL;
493 492
 
494 493
     fmap_aging(m);
... ...
@@ -529,114 +634,58 @@ void *fmap_gets(fmap_t *m, char *dst, size_t *at, size_t max_len) {
529 529
     return dst;
530 530
 }
531 531
 
532
-/* ^^^^^ POSIX STUFF AVOVE ^^^^^ */
532
+/* vvvvv MEMORY STUFF BELOW vvvvv */
533 533
 
534
-#else /* _WIN32 */
534
+static const void *mem_need(fmap_t *m, size_t at, size_t len, int lock);
535
+static void mem_unneed_off(fmap_t *m, size_t at, size_t len);
536
+static const void *mem_need_offstr(fmap_t *m, size_t at, size_t len_hint);
537
+static const void *mem_gets(fmap_t *m, char *dst, size_t *at, size_t max_len);
535 538
 
536
-/* vvvvv WIN32 STUFF BELOW vvvvv */
539
+static void unmap_none(fmap_t *m) {}
537 540
 
538
-fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty) { /* WIN32 */
539
-    unsigned int pages, mapsz, hdrsz;
540
-    unsigned short dumb = 1;
541
+extern cl_fmap_t *cl_fmap_open_memory(const void *start, size_t len)
542
+{
541 543
     int pgsz = cli_getpagesize();
542
-    struct stat st;
543
-    fmap_t *m;
544
-
545
-    *empty = 0;
546
-    if(fstat(fd, &st)) {
547
-	cli_warnmsg("fmap: fstat failed\n");
548
-	return NULL;
549
-    }
550
-    if(offset < 0 || offset != fmap_align_to(offset, pgsz)) {
551
-	cli_warnmsg("fmap: attempted mapping with unaligned offset\n");
552
-	return NULL;
553
-    }
554
-    if(!len) len = st.st_size - offset; /* bound checked later */
555
-    if(!len) {
556
-	cli_dbgmsg("fmap: attempted void mapping\n");
557
-	*empty = 1;
558
-	return NULL;
559
-    }
560
-    if(!CLI_ISCONTAINED(0, st.st_size, offset, len)) {
561
-	cli_warnmsg("fmap: attempted oof mapping\n");
562
-	return NULL;
563
-    }
564
-
565
-    pages = fmap_align_items(len, pgsz);
566
-    hdrsz = fmap_align_to(sizeof(fmap_t), pgsz);
567
-
568
-    if(!(m = (fmap_t *)cli_malloc(sizeof(fmap_t)))) {
569
-	cli_errmsg("fmap: canot allocate fmap_t\n", fd);
570
-	return NULL;
571
-    }
572
-    if((m->fh = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) {
573
-	cli_errmsg("fmap: cannot get a valid handle for descriptor %d\n", fd);
574
-	free(m);
575
-	return NULL;
576
-    }
577
-    if(!(m->mh = CreateFileMapping(m->fh, NULL, PAGE_READONLY, (DWORD)((len>>31)>>1), (DWORD)len, NULL))) {
578
-	cli_errmsg("fmap: cannot create a map of descriptor %d\n", fd);
579
-	free(m);
580
-	return NULL;
581
-    }
582
-    if(!(m->data = MapViewOfFile(m->mh, FILE_MAP_READ, (DWORD)((offset>>31)>>1), (DWORD)(offset), len))) {
583
-	cli_errmsg("fmap: cannot map file descriptor %d\n", fd);
584
-	CloseHandle(m->mh);
585
-	free(m);
544
+    cl_fmap_t *m = cli_calloc(1, sizeof(*m));
545
+    if (!m) {
546
+	cli_warnmsg("fmap: map allocation failed\n");
586 547
 	return NULL;
587 548
     }
588
-    m->fd = fd;
589
-    m->dumb = dumb;
590
-    m->mtime = st.st_mtime;
591
-    m->offset = offset;
549
+    m->data = start;
592 550
     m->len = len;
593
-    m->pages = pages;
594
-    m->hdrsz = hdrsz;
551
+    m->real_len = len;
595 552
     m->pgsz = pgsz;
596
-    m->paged = 0;
597
-    m->dont_cache_flag = 0;
553
+    m->pages = fmap_align_items(len, pgsz);
554
+    m->unmap = unmap_malloc;
555
+    m->need = mem_need;
556
+    m->need_offstr = mem_need_offstr;
557
+    m->gets = mem_gets;
558
+    m->unneed_off = mem_unneed_off;
598 559
     return m;
599 560
 }
600 561
 
601
-void funmap(fmap_t *m) { /* WIN32 */
602
-    UnmapViewOfFile(m->data);
603
-    CloseHandle(m->mh);
604
-    free((void *)m);
605
-}
606 562
 
607
-static void *fmap_need(fmap_t *m, size_t at, size_t len) { /* WIN32 */
608
-    if(!CLI_ISCONTAINED(0, m->len, at, len))
563
+static const void *mem_need(fmap_t *m, size_t at, size_t len, int lock) { /* WIN32 */
564
+    if(!len) {
609 565
 	return NULL;
610
-
611
-    if(!len)
566
+    }
567
+    at += m->nested_offset;
568
+    if(!CLI_ISCONTAINED(0, m->real_len, at, len)) {
612 569
 	return NULL;
570
+    }
571
+
613 572
     return (void *)((char *)m->data + at);
614 573
 }
615 574
 
616
-void *fmap_need_off(fmap_t *m, size_t at, size_t len) { /* WIN32 */
617
-    return fmap_need(m, at, len);
618
-}
619
-void *fmap_need_off_once(fmap_t *m, size_t at, size_t len) { /* WIN32 */
620
-    return fmap_need(m, at, len);
621
-}
622
-void *fmap_need_ptr(fmap_t *m, void *ptr, size_t len) { /* WIN32 */
623
-    return fmap_need(m, (char *)ptr - (char *)m->data, len);
624
-}
625
-void *fmap_need_ptr_once(fmap_t *m, void *ptr, size_t len) { /* WIN32 */
626
-    return fmap_need(m, (char *)ptr - (char *)m->data, len);
627
-}
628
-void fmap_unneed_off(fmap_t *m, size_t at, size_t len) { /* WIN32 */
629
-}
630
-void fmap_unneed_ptr(fmap_t *m, void *ptr, size_t len) { /* WIN32 */
631
-}
575
+static void mem_unneed_off(fmap_t *m, size_t at, size_t len) {}
632 576
 
633
-void *fmap_need_offstr(fmap_t *m, size_t at, size_t len_hint) { /* WIN32 */
577
+static const void *mem_need_offstr(fmap_t *m, size_t at, size_t len_hint) {
634 578
     char *ptr = (char *)m->data + at;
635 579
 
636
-    if(!len_hint || len_hint > m->len - at)
637
-	len_hint = m->len - at;
580
+    if(!len_hint || len_hint > m->real_len - at)
581
+	len_hint = m->real_len - at;
638 582
 
639
-    if(!CLI_ISCONTAINED(0, m->len, at, len_hint))
583
+    if(!CLI_ISCONTAINED(0, m->real_len, at, len_hint))
640 584
 	return NULL;
641 585
 
642 586
     if(memchr(ptr, 0, len_hint))
... ...
@@ -644,16 +693,11 @@ void *fmap_need_offstr(fmap_t *m, size_t at, size_t len_hint) { /* WIN32 */
644 644
     return NULL;
645 645
 }
646 646
 
647
-void *fmap_need_str(fmap_t *m, void *ptr, size_t len_hint) { /* WIN32 */
648
-    size_t at = (char *)ptr - (char *)m->data;
649
-    return fmap_need_offstr(m, at, len_hint);
650
-}
651
-
652
-void *fmap_gets(fmap_t *m, char *dst, size_t *at, size_t max_len) { /* WIN32 */
647
+static const void *mem_gets(fmap_t *m, char *dst, size_t *at, size_t max_len) {
653 648
     char *src = (char *)m->data + *at, *endptr = NULL;
654
-    size_t len = MIN(max_len-1, m->len - *at);
649
+    size_t len = MIN(max_len-1, m->real_len - *at);
655 650
 
656
-    if(!len || !CLI_ISCONTAINED(0, m->len, *at, len))
651
+    if(!len || !CLI_ISCONTAINED(0, m->real_len, *at, len))
657 652
 	return NULL;
658 653
 
659 654
     if((endptr = memchr(src, '\n', len))) {
... ...
@@ -669,30 +713,11 @@ void *fmap_gets(fmap_t *m, char *dst, size_t *at, size_t max_len) { /* WIN32 */
669 669
     return dst;
670 670
 }
671 671
 
672
-#endif /* _WIN32 */
673
-
674
-
675
-/* vvvvv SHARED STUFF BELOW vvvvv */
676
-
677 672
 fmap_t *fmap(int fd, off_t offset, size_t len) {
678 673
     int unused;
679 674
     return fmap_check_empty(fd, offset, len, &unused);
680 675
 }
681 676
 
682
-int fmap_readn(fmap_t *m, void *dst, size_t at, size_t len) {
683
-    char *src;
684
-
685
-    if(at > m->len)
686
-	return -1;
687
-    if(len > m->len - at)
688
-	len = m->len - at;
689
-    src = fmap_need_off_once(m, at, len);
690
-    if(!src)
691
-	return -1;
692
-    memcpy(dst, src, len);
693
-    return len;
694
-}
695
-
696 677
 static inline unsigned int fmap_align_items(unsigned int sz, unsigned int al) {
697 678
     return sz / al + (sz % al != 0);
698 679
 }
... ...
@@ -704,3 +729,18 @@ static inline unsigned int fmap_align_to(unsigned int sz, unsigned int al) {
704 704
 static inline unsigned int fmap_which_page(fmap_t *m, size_t at) {
705 705
     return at / m->pgsz;
706 706
 }
707
+
708
+int fmap_fd(fmap_t *m)
709
+{
710
+    int fd, ret;
711
+    if (!m->handle_is_fd)
712
+	return -1;
713
+    fd = (int)(ssize_t)m->handle;
714
+    lseek(fd, 0, SEEK_SET);
715
+    return fd;
716
+}
717
+
718
+extern void cl_fmap_close(cl_fmap_t *map)
719
+{
720
+    funmap(map);
721
+}
... ...
@@ -30,39 +30,154 @@
30 30
 #endif
31 31
 
32 32
 #include <time.h>
33
-
33
+#include <string.h>
34 34
 #include "cltypes.h"
35
+#include "clamav.h"
35 36
 
36
-typedef struct {
37
-    int fd;
38
-    unsigned short dumb;
39
-    unsigned short dont_cache_flag;
37
+struct cl_fmap;
38
+typedef cl_fmap_t fmap_t;
39
+
40
+struct cl_fmap {
41
+    /* handle interface */
42
+    void *handle;
43
+    clcb_pread pread_cb;
44
+
45
+    /* internal */
40 46
     time_t mtime;
41
-    size_t offset;
42
-    size_t len;
43 47
     unsigned int pages;
44 48
     unsigned int hdrsz;
45 49
     unsigned int pgsz;
46 50
     unsigned int paged;
51
+    unsigned short aging;
52
+    unsigned short dont_cache_flag;
53
+    unsigned short handle_is_fd;
54
+
55
+    /* memory interface */
56
+    const void *data;
57
+
58
+    /* common interface */
59
+    size_t offset;/* file offset */
60
+    size_t nested_offset;/* buffer offset for nested scan*/
61
+    size_t real_len;/* amount of data mapped from file, starting at offset */
62
+    size_t len;/* length of data accessible via current fmap */
63
+
64
+    /* real_len = nested_offset + len
65
+     * file_offset = offset + nested_offset + need_offset
66
+     * maximum offset, length accessible via fmap API: len
67
+     * offset in cached buffer: nested_offset + need_offset
68
+     *
69
+     * This allows to scan a portion of an already mapped file without dumping
70
+     * to disk and remapping (for uncompressed archives for example) */
71
+
72
+    /* vtable for implementation */
73
+    void        (*unmap)(fmap_t*);
74
+    const void* (*need)(fmap_t*, size_t at, size_t len, int lock);
75
+    const void* (*need_offstr)(fmap_t*, size_t at, size_t len_hint);
76
+    const void* (*gets)(fmap_t*, char *dst, size_t *at, size_t max_len);
77
+    void        (*unneed_off)(fmap_t*, size_t at, size_t len);
47 78
 #ifdef _WIN32
48 79
     HANDLE fh;
49 80
     HANDLE mh;
50
-    void *data;
51 81
 #endif
52 82
     uint32_t placeholder_for_bitmap;
53
-} fmap_t;
83
+};
54 84
 
55 85
 fmap_t *fmap(int fd, off_t offset, size_t len);
56 86
 fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty);
57
-void funmap(fmap_t *m);
58
-void *fmap_need_off(fmap_t *m, size_t at, size_t len);
59
-void *fmap_need_off_once(fmap_t *m, size_t at, size_t len);
60
-void *fmap_need_ptr(fmap_t *m, void *ptr, size_t len);
61
-void *fmap_need_ptr_once(fmap_t *m, void *ptr, size_t len);
62
-void fmap_unneed_off(fmap_t *m, size_t at, size_t len);
63
-void fmap_unneed_ptr(fmap_t *m, void *ptr, size_t len);
64
-int fmap_readn(fmap_t *m, void *dst, size_t at, size_t len);
65
-void *fmap_need_str(fmap_t *m, void *ptr, size_t len_hint);
66
-void *fmap_need_offstr(fmap_t *m, size_t at, size_t len_hint);
67
-void *fmap_gets(fmap_t *m, char *dst, size_t *at, size_t max_len);
87
+
88
+static inline void funmap(fmap_t *m)
89
+{
90
+    m->unmap(m);
91
+}
92
+
93
+static inline const void *fmap_need_off(fmap_t *m, size_t at, size_t len)
94
+{
95
+    return m->need(m, at, len, 1);
96
+}
97
+
98
+static inline const void *fmap_need_off_once(fmap_t *m, size_t at, size_t len)
99
+{
100
+    return m->need(m, at, len, 0);
101
+}
102
+
103
+static inline size_t fmap_ptr2off(const fmap_t *m, const void *ptr)
104
+{
105
+    return m->data ?
106
+	  (const char*)ptr - (const char*)m->data
107
+	 :(const char*)ptr - (const char*)m - m->hdrsz;
108
+}
109
+
110
+static inline const void *fmap_need_ptr(fmap_t *m, void *ptr, size_t len)
111
+{
112
+    return m->need(m, fmap_ptr2off(m, ptr), len, 1);
113
+}
114
+
115
+static inline const void *fmap_need_ptr_once(fmap_t *m, void *ptr, size_t len)
116
+{
117
+    return m->need(m, fmap_ptr2off(m, ptr), len, 0);
118
+}
119
+
120
+static inline void fmap_unneed_off(fmap_t *m, size_t at, size_t len)
121
+{
122
+    m->unneed_off(m, at, len);
123
+}
124
+
125
+static inline void fmap_unneed_ptr(fmap_t *m, void *ptr, size_t len)
126
+{
127
+    fmap_unneed_off(m, fmap_ptr2off(m, ptr), len);
128
+}
129
+
130
+static inline int fmap_readn(fmap_t *m, void *dst, size_t at, size_t len)
131
+{
132
+    const void *src;
133
+
134
+    if(at == m->len)
135
+	return 0;
136
+    if(at > m->len)
137
+	return -1;
138
+    if(len > m->len - at)
139
+	len = m->len - at;
140
+    src = fmap_need_off_once(m, at, len);
141
+    if(!src)
142
+	return -1;
143
+    memcpy(dst, src, len);
144
+    return len;
145
+}
146
+
147
+static inline const void *fmap_need_str(fmap_t *m, void *ptr, size_t len_hint)
148
+{
149
+    return m->need_offstr(m, fmap_ptr2off(m, ptr), len_hint);
150
+}
151
+
152
+static inline const void *fmap_need_offstr(fmap_t *m, size_t at, size_t len_hint)
153
+{
154
+    return m->need_offstr(m, at, len_hint);
155
+}
156
+
157
+static inline const void *fmap_gets(fmap_t *m, char *dst, size_t *at, size_t max_len) {
158
+    return m->gets(m, dst, at, max_len);
159
+}
160
+
161
+static inline const void *fmap_need_off_once_len(fmap_t *m, size_t at, size_t len, size_t *lenout)
162
+{
163
+    const void *p;
164
+    if(at >= m->len) {
165
+	*lenout = 0;
166
+	return NULL;
167
+    }
168
+    if(len > m->len - at)
169
+	len = m->len - at;
170
+    p = fmap_need_off_once(m, at, len);
171
+    *lenout = p ? len : 0;
172
+    return p;
173
+}
174
+
175
+static inline const void *fmap_need_ptr_once_len(fmap_t *m, const void *ptr, size_t len, size_t *lenout)
176
+{
177
+    return fmap_need_off_once_len(m, fmap_ptr2off(m, ptr), len, lenout);
178
+}
179
+
180
+/* deprecated */
181
+int fmap_fd(fmap_t *m);
182
+
68 183
 #endif
... ...
@@ -1722,36 +1722,29 @@ int html_normalise_map(fmap_t *map, const char *dirname, tag_arguments_t *hrefs,
1722 1722
 	return retval;
1723 1723
 }
1724 1724
 
1725
-int html_screnc_decode(int fd, const char *dirname)
1725
+int html_screnc_decode(fmap_t *map, const char *dirname)
1726 1726
 {
1727
-	int fd_tmp, count, retval=FALSE;
1727
+	int count, retval=FALSE;
1728 1728
 	unsigned char *line, tmpstr[6];
1729 1729
 	unsigned char *ptr, filename[1024];
1730
-	FILE *stream_in;
1731 1730
 	int ofd;
1732 1731
 	struct screnc_state screnc_state;
1732
+	m_area_t m_area;
1733 1733
 
1734
-	lseek(fd, 0, SEEK_SET);
1735
-	fd_tmp = dup(fd);
1736
-	if (fd_tmp < 0) {
1737
-		return FALSE;
1738
-	}
1739
-	stream_in = fdopen(fd_tmp, "r");
1740
-	if (!stream_in) {
1741
-		close(fd_tmp);
1742
-		return FALSE;
1743
-	}
1734
+	memset(&m_area, 0, sizeof(m_area));
1735
+	m_area.length = map->len;
1736
+	m_area.offset = 0;
1737
+	m_area.map = map;
1744 1738
 
1745 1739
 	snprintf((char*)filename, 1024, "%s"PATHSEP"screnc.html", dirname);
1746 1740
 	ofd = open((const char*)filename, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
1747 1741
 
1748 1742
 	if (ofd < 0) {
1749 1743
 		cli_dbgmsg("open failed: %s\n", filename);
1750
-		fclose(stream_in);
1751 1744
 		return FALSE;
1752 1745
 	}
1753 1746
 
1754
-	while ((line = cli_readchunk(stream_in, NULL, 8192)) != NULL) {
1747
+	while ((line = cli_readchunk(NULL, &m_area, 8192)) != NULL) {
1755 1748
 		ptr = (unsigned char*)strstr((char*)line, "#@~^");
1756 1749
 		if (ptr) {
1757 1750
 			break;
... ...
@@ -1768,7 +1761,7 @@ int html_screnc_decode(int fd, const char *dirname)
1768 1768
 	do {
1769 1769
 		if (! *ptr) {
1770 1770
 			free(line);
1771
-			ptr = line = cli_readchunk(stream_in, NULL, 8192);
1771
+			ptr = line = cli_readchunk(NULL, &m_area, 8192);
1772 1772
 			if (!line) {
1773 1773
 				goto abort;
1774 1774
 			}
... ...
@@ -1795,7 +1788,7 @@ int html_screnc_decode(int fd, const char *dirname)
1795 1795
 		cli_writen(ofd, ptr, strlen((const char*)ptr));
1796 1796
 		free(line);
1797 1797
 		if (screnc_state.length) {
1798
-			ptr = line = cli_readchunk(stream_in, NULL, 8192);
1798
+			ptr = line = cli_readchunk(NULL, &m_area, 8192);
1799 1799
 		}
1800 1800
 	}
1801 1801
 	cli_writen(ofd, "</script>",strlen("</script>"));
... ...
@@ -1804,7 +1797,6 @@ int html_screnc_decode(int fd, const char *dirname)
1804 1804
 	retval = TRUE;
1805 1805
 
1806 1806
 abort:
1807
-	fclose(stream_in);
1808 1807
 	close(ofd);
1809 1808
 	return retval;
1810 1809
 }
... ...
@@ -40,7 +40,7 @@ typedef struct m_area_tag {
40 40
 int html_normalise_mem(unsigned char *in_buff, off_t in_size, const char *dirname, tag_arguments_t *hrefs,const struct cli_dconf* dconf);
41 41
 int html_normalise_map(fmap_t *map, const char *dirname, tag_arguments_t *hrefs, const struct cli_dconf* dconf);
42 42
 void html_tag_arg_free(tag_arguments_t *tags);
43
-int html_screnc_decode(int fd, const char *dirname);
43
+int html_screnc_decode(fmap_t *map, const char *dirname);
44 44
 void html_tag_arg_add(tag_arguments_t *tags, const char *tag, char *value);
45 45
  
46 46
 #endif
... ...
@@ -37,6 +37,10 @@ CLAMAV_PUBLIC {
37 37
     cl_statinidir;
38 38
     cl_countsigs;
39 39
     cl_strerror;
40
+    cl_fmap_open_handle;
41
+    cl_fmap_open_memory;
42
+    cl_scanmap_callback;
43
+    cl_fmap_close;
40 44
 };
41 45
 CLAMAV_PRIVATE {
42 46
   global:
... ...
@@ -177,7 +181,6 @@ CLAMAV_PRIVATE {
177 177
     cli_bytecode_debug;
178 178
     cli_hex2ui;
179 179
     fmap;
180
-    funmap;
181 180
     cli_bytecode_context_set_trace;
182 181
     cli_bytecode_debug_printsrc;
183 182
     cli_bytecode_printversion;
... ...
@@ -185,6 +188,7 @@ CLAMAV_PRIVATE {
185 185
     cli_printcxxver;
186 186
     cli_detect_environment;
187 187
     cli_disasm_one;
188
+    cli_utf16_to_utf8;
188 189
   local:
189 190
     *;
190 191
 };
... ...
@@ -27,6 +27,8 @@
27 27
 #include "lzma_iface.h"
28 28
 
29 29
 void *__lzma_wrap_alloc(void *unused, size_t size) { 
30
+    if(!size || size > CLI_MAX_ALLOCATION)
31
+	return NULL;
30 32
     unused = unused;
31 33
     if(!size || size > CLI_MAX_ALLOCATION) {
32 34
 	cli_dbgmsg("lzma_wrap_alloc(): Attempt to allocate %lu bytes.\n", (unsigned long int) size);
... ...
@@ -552,7 +552,7 @@ int cli_scanmacho_unibin(cli_ctx *ctx)
552 552
 	cli_dbgmsg("UNIBIN: Binary %u of %u\n", i + 1, fat_header.nfats);
553 553
 	cli_dbgmsg("UNIBIN: File offset: %u\n", fat_arch.offset);
554 554
 	cli_dbgmsg("UNIBIN: File size: %u\n", fat_arch.size);
555
-	ret = cli_dumpscan(map->fd, fat_arch.offset, fat_arch.size, ctx);
555
+	ret = cli_map_scandesc(map, fat_arch.offset, fat_arch.size, ctx);
556 556
 	if(ret == CL_VIRUS)
557 557
 	    break;
558 558
     }
... ...
@@ -357,9 +357,9 @@ static int ac_maketrans(struct cli_matcher *root)
357 357
 		if (list) {
358 358
 		    while (list->next) list = list->next;
359 359
 		    list->next = child->fail->list;
360
-		}
360
+		} else
361
+		    child->list = child->fail->list;
361 362
 		child->trans = child->fail->trans;
362
-		child->fail = NULL;
363 363
 	    } else {
364 364
 		if((ret = bfs_enqueue(&bfs, &bfs_last, child)) != 0)
365 365
 		    return ret;
... ...
@@ -470,7 +470,9 @@ void cli_ac_free(struct cli_matcher *root)
470 470
 	mpool_free(root->mempool, root->ac_reloff);
471 471
 
472 472
     for(i = 0; i < root->ac_nodes; i++) {
473
-	if(!IS_LEAF(root->ac_nodetable[i]) && root->ac_nodetable[i]->fail)
473
+	if(!IS_LEAF(root->ac_nodetable[i]) &&
474
+	   root->ac_nodetable[i]->fail &&
475
+	   root->ac_nodetable[i]->trans != root->ac_nodetable[i]->fail->trans)
474 476
 	    mpool_free(root->mempool, root->ac_nodetable[i]->trans);
475 477
 	mpool_free(root->mempool, root->ac_nodetable[i]);
476 478
     }
... ...
@@ -1180,11 +1182,13 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1180 1180
 	current = current->trans[buffer[i]];
1181 1181
 
1182 1182
 	if(UNLIKELY(IS_FINAL(current))) {
1183
+	    struct cli_ac_patt *faillist = current->fail->list;
1183 1184
 	    patt = current->list;
1184 1185
 	    while(patt) {
1185 1186
 		if(patt->partno > mdata->min_partno) {
1186
-		    patt = NULL;
1187
-		    break;
1187
+		    patt = faillist;
1188
+		    faillist = NULL;
1189
+		    continue;
1188 1190
 		}
1189 1191
 		bp = i + 1 - patt->depth;
1190 1192
 		if(patt->offdata[0] != CLI_OFF_VERSION && patt->offdata[0] != CLI_OFF_MACRO && !patt->next_same && (patt->offset_min != CLI_OFF_ANY) && (!patt->sigid || patt->partno == 1)) {
... ...
@@ -1642,16 +1646,11 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
1642 1642
 		newspecial->type = AC_SPECIAL_WHITE;
1643 1643
 	    */
1644 1644
 	    } else {
1645
+		newspecial->num = 1;
1645 1646
 		for(i = 0; i < strlen(pt); i++)
1646 1647
 		    if(pt[i] == '|')
1647 1648
 			newspecial->num++;
1648 1649
 
1649
-		if(!newspecial->num) {
1650
-		    error = CL_EMALFDB;
1651
-		    break;
1652
-		} else
1653
-		    newspecial->num++;
1654
-
1655 1650
 		if(3 * newspecial->num - 1 == (uint16_t) strlen(pt)) {
1656 1651
 		    newspecial->type = AC_SPECIAL_ALT_CHAR;
1657 1652
 		    newspecial->str = (unsigned char *) mpool_malloc(root->mempool, newspecial->num);
... ...
@@ -1665,13 +1664,21 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
1665 1665
 		}
1666 1666
 
1667 1667
 		for(i = 0; i < newspecial->num; i++) {
1668
-		    if(!(h = cli_strtok(pt, i, "|"))) {
1669
-			error = CL_EMALFDB;
1670
-			break;
1671
-		    }
1668
+			unsigned int clen;
1672 1669
 
1673
-		    if(!(c = (char*)cli_mpool_hex2str(root->mempool, h))) {
1670
+		    if(newspecial->num == 1) {
1671
+			c = (char *) cli_mpool_hex2str(root->mempool, pt);
1672
+			clen = strlen(pt) / 2;
1673
+		    } else {
1674
+			if(!(h = cli_strtok(pt, i, "|"))) {
1675
+			    error = CL_EMEM;
1676
+			    break;
1677
+			}
1678
+			c = (char *) cli_mpool_hex2str(root->mempool, h);
1679
+			clen = strlen(h) / 2;
1674 1680
 			free(h);
1681
+		    }
1682
+		    if(!c) {
1675 1683
 			error = CL_EMALFDB;
1676 1684
 			break;
1677 1685
 		    }
... ...
@@ -1690,19 +1697,17 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
1690 1690
 				cli_errmsg("cli_ac_addsig: Can't allocate specialpt->next\n");
1691 1691
 				error = CL_EMEM;
1692 1692
 				free(c);
1693
-				free(h);
1694 1693
 				break;
1695 1694
 			    }
1696 1695
 			    specialpt->next->str = (unsigned char *) c;
1697
-			    specialpt->next->len = strlen(h) / 2;
1696
+			    specialpt->next->len = clen;
1698 1697
 			} else {
1699 1698
 			    newspecial->str = (unsigned char *) c;
1700
-			    newspecial->len = strlen(h) / 2;
1699
+			    newspecial->len = clen;
1701 1700
 			}
1702 1701
 		    }
1703
-		    free(h);
1704 1702
 		}
1705
-		if(newspecial->type == AC_SPECIAL_ALT_CHAR)
1703
+		if(newspecial->num > 1 && newspecial->type == AC_SPECIAL_ALT_CHAR)
1706 1704
 		    cli_qsort(newspecial->str, newspecial->num, sizeof(unsigned char), qcompare);
1707 1705
 
1708 1706
 		if(error)
... ...
@@ -245,7 +245,15 @@ int cli_caloff(const char *offstr, const struct cli_target_info *info, unsigned
245 245
 	    offdata[1] = atoi(&offcpy[3]);
246 246
 
247 247
 	} else if(offcpy[0] == 'S') {
248
-	    if(!strncmp(offstr, "SL+", 3)) {
248
+	    if(offcpy[1] == 'E') {
249
+		if(!cli_isnumber(&offcpy[2])) {
250
+		    cli_errmsg("cli_caloff: Invalid section number\n");
251
+		    return CL_EMALFDB;
252
+		}
253
+		offdata[0] = CLI_OFF_SE;
254
+		offdata[3] = atoi(&offcpy[2]);
255
+
256
+	    } else if(!strncmp(offstr, "SL+", 3)) {
249 257
 		offdata[0] = CLI_OFF_SL_PLUS;
250 258
 		if(!cli_isnumber(&offcpy[3])) {
251 259
 		    cli_errmsg("cli_caloff: Invalid offset value\n");
... ...
@@ -303,12 +311,11 @@ int cli_caloff(const char *offstr, const struct cli_target_info *info, unsigned
303 303
 
304 304
     } else {
305 305
 	/* calculate relative offsets */
306
-	if(info->status == -1) {
307
-	    *offset_min = CLI_OFF_NONE;
308
-	    if(offset_max)
309
-		*offset_max = CLI_OFF_NONE;
306
+	*offset_min = CLI_OFF_NONE;
307
+	if(offset_max)
308
+	    *offset_max = CLI_OFF_NONE;
309
+	if(info->status == -1)
310 310
 	    return CL_SUCCESS;
311
-	}
312 311
 
313 312
 	switch(offdata[0]) {
314 313
 	    case CLI_OFF_EOF_MINUS:
... ...
@@ -333,6 +340,16 @@ int cli_caloff(const char *offstr, const struct cli_target_info *info, unsigned
333 333
 		else
334 334
 		    *offset_min = info->exeinfo.section[offdata[3]].raw + offdata[1];
335 335
 		break;
336
+
337
+	    case CLI_OFF_SE:
338
+		if(offdata[3] >= info->exeinfo.nsections) {
339
+		    *offset_min = CLI_OFF_NONE;
340
+		} else {
341
+		    *offset_min = info->exeinfo.section[offdata[3]].raw;
342
+		    *offset_max = *offset_min + info->exeinfo.section[offdata[3]].rsz + offdata[2];
343
+		}
344
+		break;
345
+
336 346
 	    case CLI_OFF_VERSION:
337 347
 		*offset_min = *offset_max = CLI_OFF_ANY;
338 348
 		break;
... ...
@@ -341,12 +358,8 @@ int cli_caloff(const char *offstr, const struct cli_target_info *info, unsigned
341 341
 		return CL_EARG;
342 342
 	}
343 343
 
344
-	if(offset_max) {
345
-	    if(*offset_min != CLI_OFF_NONE)
346
-		*offset_max = *offset_min + offdata[2];
347
-	    else
348
-		*offset_max = CLI_OFF_NONE;
349
-	}
344
+	if(offset_max && *offset_max == CLI_OFF_NONE && *offset_min != CLI_OFF_NONE)
345
+	    *offset_max = *offset_min + offdata[2];
350 346
     }
351 347
 
352 348
     return CL_SUCCESS;
... ...
@@ -450,7 +463,7 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
450 450
 #endif
451 451
 
452 452
     if (ctx->engine->cb_hash)
453
-	ctx->engine->cb_hash(ctx->fmap[0]->fd, size, md5, ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx);
453
+	ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, md5, ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx);
454 454
 
455 455
     return CL_VIRUS;
456 456
 }
... ...
@@ -559,7 +572,7 @@ int cli_lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *ac
559 559
 		if(memcmp(ctx->handlertype_hash, hash, 16)) {
560 560
 		    ctx->recursion++;
561 561
 		    memcpy(ctx->handlertype_hash, hash, 16);
562
-		    if(cli_magic_scandesc_type(map->fd, ctx, root->ac_lsigtable[i]->tdb.handlertype[0]) == CL_VIRUS) {
562
+		    if(cli_magic_scandesc_type(ctx, root->ac_lsigtable[i]->tdb.handlertype[0]) == CL_VIRUS) {
563 563
 			ctx->recursion--;
564 564
 			return CL_VIRUS;
565 565
 		    }
... ...
@@ -161,6 +161,7 @@ static const struct cli_mtarget cli_mtargets[CLI_MTARGETS] =  {
161 161
 #define CLI_OFF_SX_PLUS     6
162 162
 #define CLI_OFF_VERSION     7
163 163
 #define CLI_OFF_MACRO       8
164
+#define CLI_OFF_SE	    9
164 165
 
165 166
 int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata);
166 167
 
... ...
@@ -186,7 +186,7 @@ typedef	struct	mbox_ctx {
186 186
 #define UNLOCKFILE(fp)
187 187
 #endif
188 188
 
189
-static	int	cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx);
189
+static	int	cli_parse_mbox(const char *dir, cli_ctx *ctx);
190 190
 static	message	*parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821Table, const char *firstLine, const char *dir);
191 191
 static	message	*parseEmailHeaders(message *m, const table_t *rfc821Table);
192 192
 static	int	parseEmailHeader(message *m, const char *line, const table_t *rfc821Table);
... ...
@@ -302,13 +302,13 @@ static	pthread_mutex_t	tables_mutex = PTHREAD_MUTEX_INITIALIZER;
302 302
 #endif
303 303
 
304 304
 int
305
-cli_mbox(const char *dir, int desc, cli_ctx *ctx)
305
+cli_mbox(const char *dir, cli_ctx *ctx)
306 306
 {
307 307
 	if(dir == NULL) {
308 308
 		cli_dbgmsg("cli_mbox called with NULL dir\n");
309 309
 		return CL_ENULLARG;
310 310
 	}
311
-	return cli_parse_mbox(dir, desc, ctx);
311
+	return cli_parse_mbox(dir, ctx);
312 312
 }
313 313
 
314 314
 /*
... ...
@@ -327,7 +327,7 @@ cli_mbox(const char *dir, int desc, cli_ctx *ctx)
327 327
  *	e.g. \0Content-Type: application/binary;
328 328
  */
329 329
 static int
330
-cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx)
330
+cli_parse_mbox(const char *dir, cli_ctx *ctx)
331 331
 {
332 332
 	int retcode;
333 333
 	message *body;
... ...
@@ -50,6 +50,6 @@ typedef enum {
50 50
 #include "uuencode.h"
51 51
 
52 52
 size_t	strstrip(char *s);	/* remove trailing white space */
53
-int	cli_mbox(const char *dir, int desc, cli_ctx *ctx);
53
+int	cli_mbox(const char *dir, cli_ctx *ctx);
54 54
 
55 55
 #endif /* __MBOX_H */
... ...
@@ -33,6 +33,7 @@
33 33
 #include "cltypes.h"
34 34
 #include "others.h"
35 35
 #include "msexpand.h"
36
+#include "fmap.h"
36 37
 
37 38
 #ifndef HAVE_ATTRIB_PACKED
38 39
 #define __attribute__(x)
... ...
@@ -72,12 +73,13 @@ struct msexp_hdr {
72 72
 #define RW_SIZE 2048
73 73
 
74 74
 #define READBYTES				\
75
-    ret = cli_readn(fd, rbuff, RW_SIZE);		\
76
-    if(ret == -1)				\
77
-	return CL_EREAD;			\
78
-    if(!ret)					\
75
+    rbytes = MIN(RW_SIZE, map->len - cur_off);  \
76
+    if(!rbytes)					\
79 77
 	break;					\
80
-    rbytes = (unsigned int) ret;		\
78
+    rbuff = fmap_need_off_once(map, cur_off, rbytes); \
79
+    if(!rbuff)					\
80
+	return CL_EREAD;			\
81
+    cur_off += rbytes;				\
81 82
     r = 0;
82 83
 
83 84
 #define WRITEBYTES				\
... ...
@@ -85,31 +87,35 @@ struct msexp_hdr {
85 85
     if(ret == -1 || (unsigned int) ret != w)	\
86 86
 	return CL_EWRITE;			\
87 87
     wbytes += w;				\
88
-    if(wbytes >= EC32(hdr.fsize))		\
88
+    if(wbytes >= fsize)				\
89 89
 	return CL_SUCCESS;			\
90 90
     w = 0;
91 91
 
92 92
 
93
-int cli_msexpand(int fd, int ofd, cli_ctx *ctx)
93
+int cli_msexpand(cli_ctx *ctx, int ofd)
94 94
 {
95
-	struct msexp_hdr hdr;
95
+	struct msexp_hdr *hdr;
96 96
 	uint8_t i, mask, bits;
97
-	unsigned char buff[B_SIZE], rbuff[RW_SIZE], wbuff[RW_SIZE];
97
+	unsigned char buff[B_SIZE], wbuff[RW_SIZE];
98
+	const unsigned char *rbuff;
98 99
 	unsigned int j = B_SIZE - 16, k, l, r = 0, w = 0, rbytes = 0, wbytes = 0;
100
+	fmap_t *map = *ctx->fmap;
101
+	off_t cur_off = sizeof(*hdr);
102
+	unsigned int fsize;
99 103
 	int ret;
100 104
 
101
-
102
-    if(cli_readn(fd, &hdr, sizeof(hdr)) == -1)
105
+    if(!(hdr = fmap_need_off_once(map, 0, sizeof(*hdr))))
103 106
 	return CL_EREAD;
104 107
 
105
-    if(EC32(hdr.magic1) != MAGIC1 || EC32(hdr.magic2) != MAGIC2 || EC16(hdr.magic3) != MAGIC3) {
108
+    if(EC32(hdr->magic1) != MAGIC1 || EC32(hdr->magic2) != MAGIC2 || EC16(hdr->magic3) != MAGIC3) {
106 109
 	cli_dbgmsg("MSEXPAND: Not supported file format\n");
107 110
 	return CL_EFORMAT;
108 111
     }
109 112
 
110
-    cli_dbgmsg("MSEXPAND: File size from header: %u\n", EC32(hdr.fsize));
113
+    fsize = EC32(hdr->fsize);
114
+    cli_dbgmsg("MSEXPAND: File size from header: %u\n", fsize);
111 115
 
112
-    if(cli_checklimits("MSEXPAND", ctx, EC32(hdr.fsize), 0, 0)!=CL_CLEAN)
116
+    if(cli_checklimits("MSEXPAND", ctx, fsize, 0, 0)!=CL_CLEAN)
113 117
         return CL_SUCCESS;
114 118
 
115 119
     memset(buff, 0, B_SIZE);
... ...
@@ -23,6 +23,6 @@
23 23
 
24 24
 #include "others.h"
25 25
 
26
-int cli_msexpand(int fd, int ofd, cli_ctx *ctx);
26
+int cli_msexpand(cli_ctx *ctx, int ofd);
27 27
 
28 28
 #endif
... ...
@@ -124,7 +124,7 @@ static const unsigned short mszip_bit_mask_tab[17] = {
124 124
 } while (0)
125 125
 
126 126
 static int mszip_read_input(struct mszip_stream *zip) {
127
-  int nread = zip->read_cb ? zip->read_cb(zip->file, zip->inbuf, (int)zip->inbuf_size) : cli_readn(zip->fd, zip->inbuf, (int)zip->inbuf_size);
127
+  int nread = zip->read_cb(zip->file, zip->inbuf, (int)zip->inbuf_size);
128 128
   if (nread < 0) {
129 129
     if (zip->file->error == CL_BREAK)
130 130
       return zip->error = CL_BREAK;
... ...
@@ -580,8 +580,7 @@ static int mszip_flush_window(struct mszip_stream *zip,
580 580
   return 0;
581 581
 }
582 582
 
583
-struct mszip_stream *mszip_init(int fd,
584
-				  int ofd,
583
+struct mszip_stream *mszip_init(int ofd,
585 584
 				  int input_buffer_size,
586 585
 				  int repair_mode,
587 586
 				  struct cab_file *file,
... ...
@@ -605,7 +604,6 @@ struct mszip_stream *mszip_init(int fd,
605 605
   }
606 606
 
607 607
   /* initialise decompression state */
608
-  zip->fd	       = fd;
609 608
   zip->ofd	       = ofd;
610 609
   zip->wflag	       = 1;
611 610
   zip->inbuf_size      = input_buffer_size;
... ...
@@ -769,7 +767,7 @@ void mszip_free(struct mszip_stream *zip) {
769 769
 } while (0)
770 770
 
771 771
 static int lzx_read_input(struct lzx_stream *lzx) {
772
-  int bread = lzx->read_cb ? lzx->read_cb(lzx->file, &lzx->inbuf[0], (int)lzx->inbuf_size) : cli_readn(lzx->fd, &lzx->inbuf[0], (int)lzx->inbuf_size);
772
+  int bread = lzx->read_cb(lzx->file, &lzx->inbuf[0], (int)lzx->inbuf_size);
773 773
   if (bread < 0) {
774 774
     if (lzx->file->error == CL_BREAK)
775 775
       return lzx->error = CL_BREAK;
... ...
@@ -1004,8 +1002,7 @@ static void lzx_reset_state(struct lzx_stream *lzx) {
1004 1004
 
1005 1005
 /*-------- main LZX code --------*/
1006 1006
 
1007
-struct lzx_stream *lzx_init(int fd,
1008
-			      int ofd,
1007
+struct lzx_stream *lzx_init(int ofd,
1009 1008
 			      int window_bits,
1010 1009
 			      int reset_interval,
1011 1010
 			      int input_buffer_size,
... ...
@@ -1055,7 +1052,6 @@ struct lzx_stream *lzx_init(int fd,
1055 1055
   }
1056 1056
 
1057 1057
   /* initialise decompression state */
1058
-  lzx->fd              = fd;
1059 1058
   lzx->ofd	       = ofd;
1060 1059
   lzx->wflag	       = 1;
1061 1060
   lzx->offset          = 0;
... ...
@@ -1602,7 +1598,7 @@ void lzx_free(struct lzx_stream *lzx) {
1602 1602
 } while (0)
1603 1603
 
1604 1604
 static int qtm_read_input(struct qtm_stream *qtm) {
1605
-  int nread = qtm->read_cb ? qtm->read_cb(qtm->file, &qtm->inbuf[0], (int)qtm->inbuf_size) : cli_readn(qtm->fd, &qtm->inbuf[0], (int)qtm->inbuf_size);
1605
+  int nread = qtm->read_cb(qtm->file, &qtm->inbuf[0], (int)qtm->inbuf_size);
1606 1606
   if (nread < 0) {
1607 1607
     if (qtm->file->error == CL_BREAK)
1608 1608
       return qtm->error = CL_BREAK;
... ...
@@ -1728,7 +1724,7 @@ static void qtm_init_model(struct qtm_model *model,
1728 1728
 
1729 1729
 /*-------- main Quantum code --------*/
1730 1730
 
1731
-struct qtm_stream *qtm_init(int fd, int ofd,
1731
+struct qtm_stream *qtm_init(int ofd,
1732 1732
 			      int window_bits, int input_buffer_size,
1733 1733
 			      struct cab_file *file,
1734 1734
 			      int (*read_cb)(struct cab_file *, unsigned char *, int))
... ...
@@ -1779,7 +1775,6 @@ struct qtm_stream *qtm_init(int fd, int ofd,
1779 1779
   }
1780 1780
 
1781 1781
   /* initialise decompression state */
1782
-  qtm->fd	   = fd;
1783 1782
   qtm->ofd	   = ofd;
1784 1783
   qtm->wflag	   = 1;
1785 1784
   qtm->inbuf_size  = input_buffer_size;
... ...
@@ -55,7 +55,6 @@
55 55
 #endif
56 56
 
57 57
 struct mszip_stream {
58
-  int fd;		    /* input file descriptor */
59 58
   int ofd;                  /* output file descriptor */
60 59
 
61 60
   /* inflate() will call this whenever the window should be emptied. */
... ...
@@ -88,8 +87,7 @@ struct mszip_stream {
88 88
 
89 89
 };
90 90
 
91
-struct mszip_stream *mszip_init(int fd,
92
-				  int ofd,
91
+struct mszip_stream *mszip_init(int ofd,
93 92
 				  int input_buffer_size,
94 93
 				  int repair_mode,
95 94
 				  struct cab_file *file,
... ...
@@ -118,7 +116,6 @@ struct qtm_model {
118 118
 };
119 119
 
120 120
 struct qtm_stream {
121
-  int fd;                   /* input file descriptor */
122 121
   int ofd;                  /* output file descriptor */
123 122
 
124 123
   unsigned char *window;          /* decoding window                         */
... ...
@@ -176,8 +173,7 @@ struct qtm_stream {
176 176
 
177 177
 };
178 178
 
179
-extern struct qtm_stream *qtm_init(int fd,
180
-				     int ofd,
179
+extern struct qtm_stream *qtm_init(int ofd,
181 180
 				     int window_bits,
182 181
 				     int input_buffer_size,
183 182
 				     struct cab_file *file,
... ...
@@ -218,7 +214,6 @@ void qtm_free(struct qtm_stream *qtm);
218 218
 #define LZX_FRAME_SIZE (32768) /* the size of a frame in LZX */
219 219
 
220 220
 struct lzx_stream {
221
-  int fd;			  /* input file descriptor                   */
222 221
   int ofd;			  /* output file descriptor                  */
223 222
 
224 223
   off_t   offset;                 /* number of bytes actually output         */
... ...
@@ -280,8 +275,7 @@ struct lzx_stream {
280 280
 
281 281
 };
282 282
 
283
-struct lzx_stream *lzx_init(int fd,
284
-			      int ofd,
283
+struct lzx_stream *lzx_init(int ofd,
285 284
 			      int window_bits,
286 285
 			      int reset_interval,
287 286
 			      int input_buffer_size,
... ...
@@ -918,65 +918,6 @@ int cli_rmdirs(const char *dirname)
918 918
 }
919 919
 #endif
920 920
 
921
-int cli_dumpscan(int fd, off_t offset, size_t size, cli_ctx *ctx)
922
-{
923
-	int newfd, bread, sum = 0, ret;
924
-	char buff[FILEBUFF];
925
-	char *name;
926
-
927
-    if(offset) {
928
-	if(lseek(fd, offset, SEEK_SET) == -1) {
929
-	    cli_dbgmsg("cli_dumpscan: Can't lseek to %u\n", (unsigned int) offset);
930
-	    return CL_EFORMAT; /* most likely because of corrupted file */
931
-	}
932
-    }
933
-
934
-    if(!(name = cli_gentemp(ctx->engine->tmpdir)))
935
-	return CL_EMEM;
936
-
937
-    if((newfd = open(name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
938
-	cli_errmsg("cli_dumpscan: Can't create file %s\n", name);
939
-	free(name);
940
-	return CL_ECREAT;
941
-    }
942
-
943
-    while((bread = cli_readn(fd, buff, FILEBUFF)) > 0) {
944
-	if((uint32_t) (sum + bread) >= size) {
945
-	    if(write(newfd, buff, size - sum) == -1) {
946
-		cli_errmsg("cli_dumpscan: Can't write to %s\n", name);
947
-		close(newfd);
948
-		cli_unlink(name);
949
-		free(name);
950
-		return CL_EWRITE;
951
-	    }
952
-	    break;
953
-	} else {
954
-	    if(write(newfd, buff, bread) == -1) {
955
-		cli_errmsg("cli_dumpscan: Can't write to %s\n", name);
956
-		close(newfd);
957
-		cli_unlink(name);
958
-		free(name);
959
-		return CL_EWRITE;
960
-	    }
961
-	}
962
-	sum += bread;
963
-    }
964
-    cli_dbgmsg("DUMP&SCAN: File extracted to %s\n", name);
965
-    lseek(newfd, 0, SEEK_SET);
966
-    if((ret = cli_magic_scandesc(newfd, ctx)) == CL_VIRUS)
967
-	cli_dbgmsg("cli_dumpscan: Infected with %s\n", *ctx->virname);
968
-
969
-    close(newfd);
970
-    if(!ctx->engine->keeptmp) {
971
-	if(cli_unlink(name)) {
972
-	    free(name);
973
-	    return CL_EUNLINK;
974
-	}
975
-    }
976
-    free(name);
977
-    return ret;
978
-}
979
-
980 921
 /* Implement a generic bitset, trog@clamav.net */
981 922
 
982 923
 #define BITS_PER_CHAR (8)
... ...
@@ -55,7 +55,7 @@
55 55
  * in re-enabling affected modules.
56 56
  */
57 57
 
58
-#define CL_FLEVEL 71
58
+#define CL_FLEVEL 72
59 59
 #define CL_FLEVEL_DCONF	CL_FLEVEL
60 60
 #define CL_FLEVEL_SIGTOOL CL_FLEVEL
61 61
 
... ...
@@ -527,7 +527,7 @@ char *cli_gentemp(const char *dir);
527 527
 int cli_gentempfd(const char *dir, char **name, int *fd);
528 528
 unsigned int cli_rndnum(unsigned int max);
529 529
 int cli_filecopy(const char *src, const char *dest);
530
-int cli_dumpscan(int fd, off_t offset, size_t size, cli_ctx *ctx);
530
+int cli_mapscan(fmap_t *map, off_t offset, size_t size, cli_ctx *ctx);
531 531
 bitset_t *cli_bitset_init(void);
532 532
 void cli_bitset_free(bitset_t *bs);
533 533
 int cli_bitset_set(bitset_t *bs, unsigned long bit_offset);
... ...
@@ -54,7 +54,10 @@ static	char	const	rcsid[] = "$Id: pdf.c,v 1.61 2007/02/12 20:46:09 njh Exp $";
54 54
 #include "bytecode_api.h"
55 55
 #include "md5.h"
56 56
 #include "arc4.h"
57
+#include "rijndael.h"
57 58
 #include "sha256.h"
59
+#include "textnorm.h"
60
+
58 61
 
59 62
 #ifdef	CL_DEBUG
60 63
 /*#define	SAVE_TMP	
... ...
@@ -88,10 +91,24 @@ static int xrefCheck(const char *xref, const char *eof)
88 88
     return -1;
89 89
 }
90 90
 
91
+enum enc_method {
92
+    ENC_UNKNOWN,
93
+    ENC_NONE,
94
+    ENC_IDENTITY,
95
+    ENC_V2,
96
+    ENC_AESV2,
97
+    ENC_AESV3
98
+};
99
+
91 100
 struct pdf_struct {
92 101
     struct pdf_obj *objs;
93 102
     unsigned nobjs;
94 103
     unsigned flags;
104
+    unsigned enc_method_stream;
105
+    unsigned enc_method_string;
106
+    unsigned enc_method_embeddedfile;
107
+    const char *CF;
108
+    long CF_n;
95 109
     const char *map;
96 110
     off_t size;
97 111
     off_t offset;
... ...
@@ -106,6 +123,17 @@ struct pdf_struct {
106 106
     unsigned keylen;
107 107
 };
108 108
 
109
+/* define this to be noisy about things that we can't parse properly */
110
+/*#define NOISY*/
111
+
112
+#ifdef NOISY
113
+#define noisy_msg(pdf, ...) cli_infomsg(pdf->ctx, __VA_ARGS__)
114
+#define noisy_warnmsg cli_warnmsg
115
+#else
116
+#define noisy_msg (void)
117
+#define noisy_warnmsg (void)
118
+#endif
119
+
109 120
 static const char *findNextNonWSBack(const char *q, const char *start)
110 121
 {
111 122
     while (q > start &&
... ...
@@ -116,7 +144,8 @@ static const char *findNextNonWSBack(const char *q, const char *start)
116 116
     return q;
117 117
 }
118 118
 
119
-static int find_stream_bounds(const char *start, off_t bytesleft, off_t bytesleft2, off_t *stream, off_t *endstream)
119
+static int find_stream_bounds(const char *start, off_t bytesleft, off_t bytesleft2, off_t *stream, off_t *endstream,
120
+			      int newline_hack)
120 121
 {
121 122
     const char *q2, *q;
122 123
     if ((q2 = cli_memstr(start, bytesleft, "stream", 6))) {
... ...
@@ -124,9 +153,11 @@ static int find_stream_bounds(const char *start, off_t bytesleft, off_t byteslef
124 124
 	bytesleft -= q2 - start;
125 125
 	if (bytesleft < 0)
126 126
 	    return 0;
127
-	if (bytesleft >= 2 && q2[0] == '\xd' && q2[1] == '\xa')
127
+	if (bytesleft >= 2 && q2[0] == '\xd' && q2[1] == '\xa') {
128 128
 	    q2 += 2;
129
-	if (q2[0] == '\xa')
129
+	    if (newline_hack && q2[0] == '\xa')
130
+		q2++;
131
+	} else if (q2[0] == '\xa')
130 132
 	    q2++;
131 133
 	*stream = q2 - start;
132 134
 	bytesleft2 -= q2 - start;
... ...
@@ -195,7 +226,7 @@ static int pdf_findobj(struct pdf_struct *pdf)
195 195
 	if (!q2)
196 196
 	    q2 = pdf->map + pdf->size;
197 197
 	bytesleft -= q2 - q;
198
-	if (find_stream_bounds(q-1, q2-q, bytesleft + (q2-q), &p_stream, &p_endstream)) {
198
+	if (find_stream_bounds(q-1, q2-q, bytesleft + (q2-q), &p_stream, &p_endstream, 1)) {
199 199
 	    obj->flags |= 1 << OBJ_STREAM;
200 200
 	    q2 = q-1 + p_endstream + 9;
201 201
 	    bytesleft -= q2 - q + 1;
... ...
@@ -397,10 +428,18 @@ static int filter_flatedecode(struct pdf_struct *pdf, struct pdf_obj *obj,
397 397
 		else
398 398
 		    cli_dbgmsg("cli_pdf: after writing %lu bytes, got error %d inflating PDF stream in %u %u obj\n",
399 399
 			       (unsigned long)nbytes, zstat, obj->id>>8, obj->id&0xff);
400
+		if(stream.msg)
401
+		    noisy_warnmsg("cli_pdf: after writing %lu bytes, got error \"%s\" inflating PDF stream in %u %u obj\n",
402
+			       (unsigned long)nbytes,
403
+			       stream.msg, obj->id>>8, obj->id&0xff);
404
+		else
405
+		    noisy_warnmsg("cli_pdf: after writing %lu bytes, got error %d inflating PDF stream in %u %u obj\n",
406
+			       (unsigned long)nbytes, zstat, obj->id>>8, obj->id&0xff);
400 407
 		/* mark stream as bad only if not encrypted */
401 408
 		inflateEnd(&stream);
402 409
 		if (!nbytes) {
403 410
 		    cli_dbgmsg("cli_pdf: dumping raw stream (probably encrypted)\n");
411
+		    noisy_warnmsg("cli_pdf: dumping raw stream, probably encrypted and we failed to decrypt'n");
404 412
 		    if (filter_writen(pdf, obj, fout, buf, len, sum) != len) {
405 413
 			cli_errmsg("cli_pdf: failed to write output file\n");
406 414
 			return CL_EWRITE;
... ...
@@ -496,7 +535,7 @@ static int find_length(struct pdf_struct *pdf,
496 496
     return length;
497 497
 }
498 498
 
499
-#define DUMP_MASK ((1 << OBJ_FILTER_FLATE) | (1 << OBJ_FILTER_DCT) | (1 << OBJ_FILTER_AH) | (1 << OBJ_FILTER_A85) | (1 << OBJ_EMBEDDED_FILE) | (1 << OBJ_JAVASCRIPT) | (1 << OBJ_OPENACTION) | (1 << OBJ_LAUNCHACTION))
499
+#define DUMP_MASK ((1 << OBJ_CONTENTS) | (1 << OBJ_FILTER_FLATE) | (1 << OBJ_FILTER_DCT) | (1 << OBJ_FILTER_AH) | (1 << OBJ_FILTER_A85) | (1 << OBJ_EMBEDDED_FILE) | (1 << OBJ_JAVASCRIPT) | (1 << OBJ_OPENACTION) | (1 << OBJ_LAUNCHACTION))
500 500
 
501 501
 static int obj_size(struct pdf_struct *pdf, struct pdf_obj *obj, int binary)
502 502
 {
... ...
@@ -558,6 +597,236 @@ static int run_pdf_hooks(struct pdf_struct *pdf, enum pdf_phase phase, int fd,
558 558
     return ret;
559 559
 }
560 560
 
561
+static void dbg_printhex(const char *msg, const char *hex, unsigned len);
562
+static void aes_decrypt(const unsigned char *in, off_t *length, unsigned char *q, char *key, unsigned key_n, int has_iv)
563
+{
564
+    unsigned long rk[RKLENGTH(256)];
565
+    unsigned char iv[16];
566
+    unsigned len = *length;
567
+    unsigned char pad, i;
568
+    int nrounds;
569
+
570
+    cli_dbgmsg("cli_pdf: aes_decrypt: key length: %d, data length: %d\n", key_n, *length);
571
+    if (key_n > 32) {
572
+	cli_dbgmsg("cli_pdf: aes_decrypt: key length is %s!\n", key_n*8);
573
+	return;
574
+    }
575
+    if (len < 32) {
576
+	cli_dbgmsg("cli_pdf: aes_decrypt: len is <32: %d\n", len);
577
+	noisy_warnmsg("cli_pdf: aes_decrypt: len is <32: %d\n", len);
578
+	return;
579
+    }
580
+    if (has_iv) {
581
+	memcpy(iv, in, 16);
582
+	in += 16;
583
+	len -= 16;
584
+    } else
585
+	memset(iv, 0, sizeof(iv));
586
+
587
+    nrounds = rijndaelSetupDecrypt(rk, key, key_n*8);
588
+    while (len >= 16) {
589
+	unsigned i;
590
+	rijndaelDecrypt(rk, nrounds, in, q);
591
+	for (i=0;i<16;i++)
592
+	    q[i] ^= iv[i];
593
+	memcpy(iv, in, 16);
594
+	q += 16;
595
+	in += 16;
596
+	len -= 16;
597
+    }
598
+    if (has_iv) {
599
+	len += 16;
600
+	pad = q[-1];
601
+	if (pad > 0x10) {
602
+	    cli_dbgmsg("cli_pdf: aes_decrypt: bad pad: %x (extra len: %d)\n", pad, len-16);
603
+	    noisy_warnmsg("cli_pdf: aes_decrypt: bad pad: %x (extra len: %d)\n", pad, len-16);
604
+	    *length -= len;
605
+	    return;
606
+	}
607
+	q -= pad;
608
+	for (i=1;i<pad;i++) {
609
+	    if (q[i] != pad) {
610
+		cli_dbgmsg("cli_pdf: aes_decrypt: bad pad: %x != %x\n",q[i],pad);
611
+		noisy_warnmsg("cli_pdf: aes_decrypt: bad pad: %x != %x\n",q[i],pad);
612
+		*length -= len;
613
+		return;
614
+	    }
615
+	}
616
+	len += pad;
617
+    }
618
+    *length -= len;
619
+    cli_dbgmsg("cli_pdf: aes_decrypt: length is %d\n", *length);
620
+}
621
+
622
+
623
+static char *decrypt_any(struct pdf_struct *pdf, uint32_t id, const char *in, off_t *length,
624
+			 enum enc_method enc_method)
625
+{
626
+    unsigned char *key, *q, result[16];
627
+    unsigned n;
628
+    cli_md5_ctx md5;
629
+    struct arc4_state arc4;
630
+
631
+    if (!length || !*length || !in) {
632
+	noisy_warnmsg("decrypt failed for obj %u %u\n", id>>8, id&0xff);
633
+	return NULL;
634
+    }
635
+    n = pdf->keylen + 5;
636
+    if (enc_method == ENC_AESV2)
637
+	n += 4;
638
+    key = cli_malloc(n);
639
+    if (!key) {
640
+	noisy_warnmsg("decrypt_any: malloc failed\n");
641
+	return NULL;
642
+    }
643
+
644
+    memcpy(key, pdf->key, pdf->keylen);
645
+    q = key + pdf->keylen;
646
+    *q++ = id >> 8;
647
+    *q++ = id >> 16;
648
+    *q++ = id >> 24;
649
+    *q++ = id;
650
+    *q++ = 0;
651
+    if (enc_method == ENC_AESV2)
652
+	memcpy(q, "sAlT", 4);
653
+    cli_md5_init(&md5);
654
+    cli_md5_update(&md5, key, n);
655
+    cli_md5_final(result, &md5);
656
+    free(key);
657
+
658
+    n = pdf->keylen + 5;
659
+    if (n > 16)
660
+	n = 16;
661
+
662
+    q = cli_malloc(*length);
663
+    if (!q) {
664
+	noisy_warnmsg("decrypt_any: malloc failed\n");
665
+	return NULL;
666
+    }
667
+
668
+    switch (enc_method) {
669
+	case ENC_V2:
670
+	    cli_dbgmsg("cli_pdf: enc is v2\n");
671
+	    memcpy(q, in, *length);
672
+	    arc4_init(&arc4, result, n);
673
+	    arc4_apply(&arc4, q, *length);
674
+	    noisy_msg(pdf, "decrypted ARC4 data\n");
675
+	    break;
676
+	case ENC_AESV2:
677
+	    cli_dbgmsg("cli_pdf: enc is aesv2\n");
678
+	    aes_decrypt(in, length, q, result, n, 1);
679
+	    noisy_msg(pdf, "decrypted AES(v2) data\n");
680
+	    break;
681
+	case ENC_AESV3:
682
+	    cli_dbgmsg("cli_pdf: enc is aesv3\n");
683
+	    aes_decrypt(in, length, q, pdf->key, pdf->keylen, 1);
684
+	    noisy_msg(pdf, "decrypted AES(v3) data\n");
685
+	    break;
686
+	case ENC_IDENTITY:
687
+	    cli_dbgmsg("cli_pdf: enc is identity\n");
688
+	    memcpy(q, in, *length);
689
+	    noisy_msg(pdf, "identity encryption\n");
690
+	    break;
691
+	case ENC_NONE:
692
+	    cli_dbgmsg("cli_pdf: enc is none\n");
693
+	    noisy_msg(pdf, "encryption is none\n");
694
+	    free(q);
695
+	    return NULL;
696
+	case ENC_UNKNOWN:
697
+	    cli_dbgmsg("cli_pdf: enc is unknown\n");
698
+	    free(q);
699
+	    noisy_warnmsg("decrypt_any: unknown encryption method for obj %u %u\n",
700
+		       id>>8,id&0xff);
701
+	    return NULL;
702
+    }
703
+    return q;
704
+}
705
+
706
+static enum enc_method get_enc_method(struct pdf_struct *pdf, struct pdf_obj *obj)
707
+{
708
+    if (obj->flags & (1 << OBJ_EMBEDDED_FILE))
709
+	return pdf->enc_method_embeddedfile;
710
+    if (obj->flags & (1 << OBJ_STREAM))
711
+	return pdf->enc_method_stream;
712
+    return pdf->enc_method_string;
713
+}
714
+
715
+enum cstate {
716
+    CSTATE_NONE,
717
+    CSTATE_TJ,
718
+    CSTATE_TJ_PAROPEN
719
+};
720
+
721
+static void process(struct text_norm_state *s, enum cstate *st, const char *buf, int length, int fout)
722
+{
723
+    do {
724
+	switch (*st) {
725
+	    case CSTATE_NONE:
726
+		if (*buf == '[') *st = CSTATE_TJ;
727
+		else {
728
+		    const char *nl = memchr(buf, '\n', length);
729
+		    if (!nl)
730
+			return;
731
+		    length -= nl - buf;
732
+		    buf = nl;
733
+		}
734
+		break;
735
+	    case CSTATE_TJ:
736
+		if (*buf == '(') *st = CSTATE_TJ_PAROPEN;
737
+		break;
738
+	    case CSTATE_TJ_PAROPEN:
739
+		if (*buf == ')') *st = CSTATE_TJ;
740
+		else {
741
+		    if (text_normalize_buffer(s, buf, 1) != 1) {
742
+			cli_writen(fout, s->out, s->out_pos);
743
+			text_normalize_reset(s);
744
+		    }
745
+		}
746
+		break;
747
+	}
748
+	buf++;
749
+	length--;
750
+    } while (length > 0);
751
+}
752
+
753
+static int pdf_scan_contents(int fd, struct pdf_struct *pdf)
754
+{
755
+    struct text_norm_state s;
756
+    char fullname[1024];
757
+    char outbuff[BUFSIZ];
758
+    char inbuf[BUFSIZ];
759
+    int fout, n, rc;
760
+    enum cstate st = CSTATE_NONE;
761
+
762
+    snprintf(fullname, sizeof(fullname), "%s"PATHSEP"pdf%02u_c", pdf->dir, (pdf->files-1));
763
+    fout = open(fullname,O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
764
+    if (fout < 0) {
765
+	char err[128];
766
+	cli_errmsg("cli_pdf: can't create temporary file %s: %s\n", fullname, cli_strerror(errno, err, sizeof(err)));
767
+	return CL_ETMPFILE;
768
+    }
769
+
770
+    text_normalize_init(&s, outbuff, sizeof(outbuff));
771
+    while (1) {
772
+	n = cli_readn(fd, inbuf, sizeof(inbuf));
773
+	if (n <= 0)
774
+	    break;
775
+	process(&s, &st, inbuf, n, fout);
776
+    }
777
+    cli_writen(fout, s.out, s.out_pos);
778
+
779
+    lseek(fout, 0, SEEK_SET);
780
+    rc = cli_magic_scandesc(fout, pdf->ctx);
781
+    close(fout);
782
+    if (!pdf->ctx->engine->keeptmp)
783
+	if (cli_unlink(fullname) && rc != CL_VIRUS)
784
+	    rc = CL_EUNLINK;
785
+    return rc;
786
+}
787
+
788
+static const char *pdf_getdict(const char *q0, int* len, const char *key);
789
+static char *pdf_readval(const char *q, int len, const char *key);
790
+static enum enc_method parse_enc_method(const char *dict, unsigned len, const char *key, enum enc_method def);
561 791
 static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
562 792
 {
563 793
     char fullname[NAME_MAX + 1];
... ...
@@ -565,6 +834,7 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
565 565
     off_t sum = 0;
566 566
     int rc = CL_SUCCESS;
567 567
     char *ascii_decoded = NULL;
568
+    char *decrypted = NULL;
568 569
     int dump = 1;
569 570
 
570 571
     /* TODO: call bytecode hook here, allow override dumpability */
... ...
@@ -585,7 +855,7 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
585 585
     }
586 586
     if (!dump)
587 587
 	return CL_CLEAN;
588
-    cli_dbgmsg("cli_pdf: dumping obj %u %u\n", obj->id>>8, obj->id);
588
+    cli_dbgmsg("cli_pdf: dumping obj %u %u\n", obj->id>>8, obj->id&0xff);
589 589
     snprintf(fullname, sizeof(fullname), "%s"PATHSEP"pdf%02u", pdf->dir, pdf->files++);
590 590
     fout = open(fullname,O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
591 591
     if (fout < 0) {
... ...
@@ -602,7 +872,9 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
602 602
 	off_t length;
603 603
 	find_stream_bounds(start, pdf->size - obj->start,
604 604
 			   pdf->size - obj->start,
605
-			   &p_stream, &p_endstream);
605
+			   &p_stream, &p_endstream,
606
+			   pdf->enc_method_stream <= ENC_IDENTITY &&
607
+			   pdf->enc_method_embeddedfile <= ENC_IDENTITY);
606 608
 	if (p_stream && p_endstream) {
607 609
 	    const char *flate_in;
608 610
 	    long ascii_decoded_size = 0;
... ...
@@ -616,6 +888,8 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
616 616
 	    if (length > pdf->size || obj->start + p_stream + length > pdf->size) {
617 617
 		cli_dbgmsg("cli_pdf: length out of file: %ld + %ld > %ld\n",
618 618
 			   p_stream, length, pdf->size);
619
+		noisy_warnmsg("length out of file, truncated: %ld + %ld > %ld\n",
620
+			   p_stream, length, pdf->size);
619 621
 		length = pdf->size - (obj->start + p_stream);
620 622
 	    }
621 623
 	    if (!(obj->flags & (1 << OBJ_FILTER_FLATE)) && length <= 0) {
... ...
@@ -648,6 +922,30 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
648 648
 	    if (!length)
649 649
 		length = size;
650 650
 
651
+	    flate_in = start + p_stream;
652
+	    if (pdf->flags & (1 << DECRYPTABLE_PDF)) {
653
+		enum enc_method enc = get_enc_method(pdf, obj);
654
+		if (obj->flags & (1 << OBJ_FILTER_CRYPT)) {
655
+		    int len = p_stream;
656
+		    const char *q = pdf_getdict(start, &len, "/DecodeParams");
657
+		    enc = ENC_IDENTITY;
658
+		    if (q && pdf->CF) {
659
+			char *name = pdf_readval(q, len, "/Name");
660
+			cli_dbgmsg("cli_pdf: Crypt filter %s\n", name);
661
+			if (name && strcmp(name, "/Identity"))
662
+			    enc = parse_enc_method(pdf->CF, pdf->CF_n, name, enc); 
663
+		    }
664
+		}
665
+		if (cli_memstr(start, p_stream, "/XRef", 5))
666
+		    cli_dbgmsg("cli_pdf: cross reference stream, skipping\n");
667
+		else {
668
+		    decrypted = decrypt_any(pdf, obj->id, flate_in, &length,
669
+					    enc);
670
+		    if (decrypted)
671
+			flate_in = decrypted;
672
+		}
673
+	    }
674
+
651 675
 	    if (obj->flags & (1 << OBJ_FILTER_AH)) {
652 676
 		ascii_decoded = cli_malloc(length/2 + 1);
653 677
 		if (!ascii_decoded) {
... ...
@@ -655,7 +953,7 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
655 655
 		    rc = CL_EMEM;
656 656
 		    break;
657 657
 		}
658
-		ascii_decoded_size = asciihexdecode(start + p_stream,
658
+		ascii_decoded_size = asciihexdecode(flate_in,
659 659
 						    length,
660 660
 						    ascii_decoded);
661 661
 	    } else if (obj->flags & (1 << OBJ_FILTER_A85)) {
... ...
@@ -665,7 +963,7 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
665 665
 		    rc = CL_EMEM;
666 666
 		    break;
667 667
 		}
668
-		ascii_decoded_size = ascii85decode(start+p_stream,
668
+		ascii_decoded_size = ascii85decode(flate_in,
669 669
 						   length,
670 670
 						   (unsigned char*)ascii_decoded);
671 671
 	    }
... ...
@@ -682,7 +980,8 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
682 682
 	    /* either direct or ascii-decoded input */
683 683
 	    if (!ascii_decoded)
684 684
 		ascii_decoded_size = length;
685
-	    flate_in = ascii_decoded ? ascii_decoded : start+p_stream;
685
+	    else
686
+		flate_in = ascii_decoded;
686 687
 
687 688
 	    if (obj->flags & (1 << OBJ_FILTER_FLATE)) {
688 689
 		cli_dbgmsg("cli_pdf: deflate len %ld (orig %ld)\n", ascii_decoded_size, (long)orig_length);
... ...
@@ -691,7 +990,9 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
691 691
 		if (filter_writen(pdf, obj, fout, flate_in, ascii_decoded_size, &sum) != ascii_decoded_size)
692 692
 		    rc = CL_EWRITE;
693 693
 	    }
694
-	}
694
+	} else
695
+	    noisy_warnmsg("cannot find stream bounds for obj %u %u\n", obj->id>>8, obj->id&0xff);
696
+
695 697
     } else if (obj->flags & (1 << OBJ_JAVASCRIPT)) {
696 698
 	const char *q2;
697 699
 	const char *q = pdf->map+obj->start;
... ...
@@ -700,6 +1001,8 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
700 700
 	if (bytesleft < 0)
701 701
 	    break;
702 702
 
703
+      do {
704
+
703 705
 	q2 = cli_memstr(q, bytesleft, "/JavaScript", 11);
704 706
 	if (!q2)
705 707
 	    break;
... ...
@@ -715,28 +1018,76 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
715 715
 	} while (*q == '/');
716 716
 	if (!q)
717 717
 	    break;
718
+
718 719
 	if (*q == '(') {
719
-	    if (filter_writen(pdf, obj, fout, q+1, bytesleft-1, &sum) != (bytesleft-1)) {
720
+	    const char *out, *q2, *end;
721
+	    long n = bytesleft;
722
+	    q++;
723
+	    n--;
724
+	    out = q;
725
+	    end = q + n;
726
+
727
+	    do {
728
+		q2 = memchr(q, ')', n);
729
+		if (q2) {
730
+		    q2++;
731
+		    n -= q2 - q;
732
+		    q = q2;
733
+		}
734
+	    } while (n > 0 && q2 && q2[-1] == '\\');
735
+	    if (q2)
736
+		end = q2-1;
737
+	    n = end - out;
738
+	    bytesleft -= q - out;
739
+
740
+	    if (pdf->flags & (1 << DECRYPTABLE_PDF)) {
741
+		cli_dbgmsg("cli_pdf: encrypted string\n");
742
+		decrypted = decrypt_any(pdf, obj->id, out, &n,
743
+					pdf->enc_method_string);
744
+		if (decrypted) {
745
+		    noisy_msg(pdf, "decrypted Javascript string from obj %u %u\n", obj->id>>8,obj->id&0xff);
746
+		    out = decrypted;
747
+		}
748
+	    }
749
+	    if (filter_writen(pdf, obj, fout, out, n, &sum) != n) {
720 750
 		rc = CL_EWRITE;
721 751
 		break;
722 752
 	    }
753
+	    cli_dbgmsg("bytesleft: %d\n", bytesleft);
723 754
 	} else if (*q == '<') {
724 755
 	    char *decoded;
756
+	    const char *out;
757
+	    long n;
725 758
 	    q2 = memchr(q+1, '>', bytesleft);
726 759
 	    if (!q2) q2 = q + bytesleft;
727
-	    decoded = cli_malloc(q2 - q);
760
+	    n = q2 - q;
761
+	    out = q;
762
+	    q += n;
763
+	    bytesleft -= n;
764
+	    n--;
765
+	    if (pdf->flags & (1 << DECRYPTABLE_PDF)) {
766
+		out++;
767
+		n--;
768
+		decrypted = decrypt_any(pdf, obj->id, out, &n, pdf->enc_method_string);
769
+		if (decrypted) {
770
+		    noisy_msg(pdf, "decrypted Javascript string from obj %u %u\n", obj->id>>8,obj->id&0xff);
771
+		    out = decrypted;
772
+		}
773
+	    }
774
+	    decoded = cli_malloc(n);
728 775
 	    if (!decoded) {
729 776
 		rc = CL_EMEM;
730 777
 		break;
731 778
 	    }
732
-	    cli_hex2str_to(q2, decoded, q2-q-1);
733
-	    decoded[q2-q-1] = '\0';
779
+	    cli_hex2str_to(out, decoded, n-1);
780
+	    decoded[n-1] = '\0';
734 781
 	    cli_dbgmsg("cli_pdf: found hexadecimal encoded javascript in %u %u obj\n",
735 782
 		       obj->id>>8, obj->id&0xff);
736 783
 	    pdfobj_flag(pdf, obj, HEX_JAVASCRIPT);
737
-	    filter_writen(pdf, obj, fout, decoded, q2-q-1, &sum);
784
+	    filter_writen(pdf, obj, fout, decoded, n-1, &sum);
738 785
 	    free(decoded);
739 786
 	}
787
+      } while (bytesleft > 0);
740 788
     } else {
741 789
 	off_t bytesleft = obj_size(pdf, obj, 0);
742 790
 	if (filter_writen(pdf, obj, fout , pdf->map + obj->start, bytesleft,&sum) != bytesleft)
... ...
@@ -758,9 +1109,18 @@ static int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj)
758 758
 	    if (rc2 == CL_VIRUS)
759 759
 		rc = rc2;
760 760
 	}
761
+	if (rc == CL_CLEAN && (obj->flags & (1 << OBJ_CONTENTS))) {
762
+	    lseek(fout, 0, SEEK_SET);
763
+	    cli_dbgmsg("cli_pdf: dumping contents %u %u\n", obj->id>>8, obj->id&0xff);
764
+	    rc2 = pdf_scan_contents(fout, pdf);
765
+	    if (rc2 == CL_VIRUS)
766
+		rc = rc2;
767
+	    noisy_msg(pdf, "extracted text from obj %u %u\n", obj->id>>8, obj->id&0xff);
768
+	}
761 769
     }
762 770
     close(fout);
763 771
     free(ascii_decoded);
772
+    free(decrypted);
764 773
     if (!pdf->ctx->engine->keeptmp)
765 774
 	if (cli_unlink(fullname) && rc != CL_VIRUS)
766 775
 	    rc = CL_EUNLINK;
... ...
@@ -775,6 +1135,7 @@ enum objstate {
775 775
     STATE_OPENACTION,
776 776
     STATE_LINEARIZED,
777 777
     STATE_LAUNCHACTION,
778
+    STATE_CONTENTS,
778 779
     STATE_ANY /* for actions table below */
779 780
 };
780 781
 
... ...
@@ -816,7 +1177,9 @@ static struct pdfname_action pdfname_actions[] = {
816 816
     {"S", OBJ_DICT, STATE_NONE, STATE_S},
817 817
     {"Type", OBJ_DICT, STATE_NONE, STATE_NONE},
818 818
     {"OpenAction", OBJ_OPENACTION, STATE_ANY, STATE_OPENACTION},
819
-    {"Launch", OBJ_LAUNCHACTION, STATE_ANY, STATE_LAUNCHACTION}
819
+    {"Launch", OBJ_LAUNCHACTION, STATE_ANY, STATE_LAUNCHACTION},
820
+    {"Page", OBJ_PAGE, STATE_NONE, STATE_NONE},
821
+    {"Contents", OBJ_CONTENTS, STATE_NONE, STATE_CONTENTS}
820 822
 };
821 823
 
822 824
 #define KNOWN_FILTERS ((1 << OBJ_FILTER_AH) | (1 << OBJ_FILTER_RL) | (1 << OBJ_FILTER_A85) | (1 << OBJ_FILTER_FLATE) | (1 << OBJ_FILTER_LZW) | (1 << OBJ_FILTER_FAX) | (1 << OBJ_FILTER_DCT) | (1 << OBJ_FILTER_JPX) | (1 << OBJ_FILTER_CRYPT))
... ...
@@ -875,12 +1238,61 @@ static void handle_pdfname(struct pdf_struct *pdf, struct pdf_obj *obj,
875 875
 
876 876
 static char *pdf_readstring(const char *q0, int len, const char *key, unsigned *slen);
877 877
 static int pdf_readint(const char *q0, int len, const char *key);
878
-static const char *pdf_getdict(const char *q0, int* len, const char *key);
878
+
879
+static void pdf_parse_encrypt(struct pdf_struct *pdf, const char *enc, int len)
880
+{
881
+    const char *q, *q2;
882
+    uint32_t objid;
883
+
884
+    if (len >= 16 && !strncmp(enc, "/EncryptMetadata", 16)) {
885
+	q = cli_memstr(enc+16, len-16, "/Encrypt", 8);
886
+	if (!q)
887
+	    return;
888
+	len -= q - enc;
889
+	enc = q;
890
+    }
891
+    q = enc + 8;
892
+    len -= 8;
893
+    q2 = pdf_nextobject(q, len);
894
+    if (!q2 || !isdigit(*q2))
895
+	return;
896
+    objid = atoi(q2) << 8;
897
+    len -= q2 - q;
898
+    q = q2;
899
+    q2 = pdf_nextobject(q, len);
900
+    if (!q2 || !isdigit(*q2))
901
+	return;
902
+    objid |= atoi(q2) & 0xff;
903
+    len -= q2 - q;
904
+    q = q2;
905
+    q2 = pdf_nextobject(q, len);
906
+    if (!q2 || *q2 != 'R')
907
+	return;
908
+    cli_dbgmsg("cli_pdf: Encrypt dictionary in obj %d %d\n", objid>>8, objid&0xff);
909
+    pdf->enc_objid = objid;
910
+}
911
+
912
+static void pdf_parse_trailer(struct pdf_struct *pdf, const char *s, long length)
913
+{
914
+    const char *enc;
915
+    enc = cli_memstr(s, length, "/Encrypt", 8);
916
+    if (enc) {
917
+	char *newID;
918
+	pdf->flags |= 1 << ENCRYPTED_PDF;
919
+	pdf_parse_encrypt(pdf, enc, s + length - enc);
920
+	newID = pdf_readstring(s, length, "/ID", &pdf->fileIDlen);
921
+	if (newID) {
922
+	    free(pdf->fileID);
923
+	    pdf->fileID = newID;
924
+	}
925
+    }
926
+}
927
+
879 928
 static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
880 929
 {
881 930
     /* enough to hold common pdf names, we don't need all the names */
882 931
     char pdfname[64];
883
-    const char *q2, *q3;
932
+    const char *q2, *q3, *q4;
884 933
     const char *q = obj->start + pdf->map;
885 934
     const char *dict, *start;
886 935
     off_t dict_length;
... ...
@@ -918,8 +1330,23 @@ static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
918 918
 	bytesleft--;
919 919
 	q = q2;
920 920
     } while (!q3 || q3[1] != '>');
921
+    q = q3 + 2;
922
+    q4 = NULL;
923
+    /* find real end of dictionary (in case of nested one)*/
924
+    do {
925
+	q2 = pdf_nextobject(q, bytesleft);
926
+	bytesleft -= q2 -q;
927
+	if (!q2 || bytesleft < 0) {
928
+	    break;
929
+	}
930
+	q4 = memchr(q-1, '>', q2-q+1);
931
+	q2++;
932
+	bytesleft--;
933
+	q = q2;
934
+    } while (!q4 || q4[1] != '>');
935
+    if (!q4) q4 = q3;
921 936
     obj->flags |= 1 << OBJ_DICT;
922
-    dict_length = q3 - dict;
937
+    dict_length = q4 - dict;
923 938
 
924 939
     /*  process pdf names */
925 940
     for (q = dict;dict_length > 0;) {
... ...
@@ -956,19 +1383,22 @@ static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
956 956
 	    objstate = STATE_NONE;
957 957
 	    trailer_end = pdf_readint(q, dict_length, "/H");
958 958
 	    if (trailer_end > 0 && trailer_end < pdf->size) {
959
+		const char *enc;
959 960
 		trailer = trailer_end - 1024;
960 961
 		if (trailer < 0) trailer = 0;
961 962
 		q2 = pdf->map + trailer;
962 963
 		cli_dbgmsg("cli_pdf: looking for trailer in linearized pdf: %ld - %ld\n", trailer, trailer_end);
963
-		pdf->fileID = pdf_readstring(q2, trailer_end - trailer, "/ID", &pdf->fileIDlen);
964
+		pdf_parse_trailer(pdf, q2, trailer_end - trailer);
964 965
 		if (pdf->fileID)
965
-		    cli_dbgmsg("found fileID\n");
966
+		    cli_dbgmsg("cli_pdf: found fileID\n");
966 967
 	    }
967 968
 	}
968 969
 	if (objstate == STATE_LAUNCHACTION)
969 970
 	    pdfobj_flag(pdf, obj, HAS_LAUNCHACTION);
970
-	if (dict_length > 0 && (objstate == STATE_JAVASCRIPT ||
971
-	    objstate == STATE_OPENACTION)) {
971
+	if (dict_length > 0 &&
972
+	    (objstate == STATE_JAVASCRIPT ||
973
+	     objstate == STATE_OPENACTION ||
974
+	     objstate == STATE_CONTENTS)) {
972 975
 	    if (objstate == STATE_OPENACTION)
973 976
 		pdfobj_flag(pdf, obj, HAS_OPENACTION);
974 977
 	    q2 = pdf_nextobject(q, dict_length);
... ...
@@ -986,8 +1416,10 @@ static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
986 986
 				   objid >> 8, objid&0xff);
987 987
 			obj2 = find_obj(pdf, obj, objid);
988 988
 			if (obj2) {
989
-			    enum pdf_objflags flag = objstate == STATE_JAVASCRIPT ?
990
-				OBJ_JAVASCRIPT : OBJ_OPENACTION;
989
+			    enum pdf_objflags flag =
990
+				objstate == STATE_JAVASCRIPT ? OBJ_JAVASCRIPT :
991
+				objstate == STATE_OPENACTION ? OBJ_OPENACTION :
992
+				OBJ_CONTENTS;
991 993
 			    obj2->flags |= 1 << flag;
992 994
 			    obj->flags &= ~(1 << flag);
993 995
 			} else {
... ...
@@ -1019,39 +1451,6 @@ static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
1019 1019
     cli_dbgmsg("cli_pdf: %u %u obj flags: %02x\n", obj->id>>8, obj->id&0xff, obj->flags);
1020 1020
 }
1021 1021
 
1022
-static void pdf_parse_encrypt(struct pdf_struct *pdf, const char *enc, int len)
1023
-{
1024
-    const char *q, *q2;
1025
-    uint32_t objid;
1026
-
1027
-    if (len >= 16 && !strncmp(enc, "/EncryptMetadata", 16)) {
1028
-	q = cli_memstr(enc+16, len-16, "/Encrypt", 8);
1029
-	if (!q)
1030
-	    return;
1031
-	len -= q - enc;
1032
-	enc = q;
1033
-    }
1034
-    q = enc + 8;
1035
-    len -= 8;
1036
-    q2 = pdf_nextobject(q, len);
1037
-    if (!q2 || !isdigit(*q2))
1038
-	return;
1039
-    objid = atoi(q2) << 8;
1040
-    len -= q2 - q;
1041
-    q = q2;
1042
-    q2 = pdf_nextobject(q, len);
1043
-    if (!q2 || !isdigit(*q2))
1044
-	return;
1045
-    objid |= atoi(q2) & 0xff;
1046
-    len -= q2 - q;
1047
-    q = q2;
1048
-    q2 = pdf_nextobject(q, len);
1049
-    if (!q2 || *q2 != 'R')
1050
-	return;
1051
-    cli_dbgmsg("cli_pdf: Encrypt dictionary in obj %d %d\n", objid>>8, objid&0xff);
1052
-    pdf->enc_objid = objid;
1053
-}
1054
-
1055 1022
 static const char *pdf_getdict(const char *q0, int* len, const char *key)
1056 1023
 {
1057 1024
     const char *q;
... ...
@@ -1191,6 +1590,31 @@ static char *pdf_readstring(const char *q0, int len, const char *key, unsigned *
1191 1191
     return NULL;
1192 1192
 }
1193 1193
 
1194
+static char *pdf_readval(const char *q, int len, const char *key)
1195
+{
1196
+    const char *end;
1197
+    char *s;
1198
+
1199
+    q = pdf_getdict(q, &len, key);
1200
+    if (!q || len <= 0)
1201
+	return NULL;
1202
+    while (len > 0 && *q && *q == ' ') { q++; len--; }
1203
+    if (*q != '/')
1204
+	return NULL;
1205
+    q++;
1206
+    len--;
1207
+    end = q;
1208
+    while (len > 0 && *end && !(*end == '/' || (len > 1 && end[0] == '>' && end[1] == '>'))) {
1209
+	end++; len--;
1210
+    }
1211
+    s = cli_malloc(end - q + 1);
1212
+    if (!s)
1213
+	return NULL;
1214
+    memcpy(s, q, end-q);
1215
+    s[end-q] = '\0';
1216
+    return s;
1217
+}
1218
+
1194 1219
 static int pdf_readint(const char *q0, int len, const char *key)
1195 1220
 {
1196 1221
     const char *q  = pdf_getdict(q0, &len, key);
... ...
@@ -1227,6 +1651,7 @@ static void dbg_printhex(const char *msg, const char *hex, unsigned len)
1227 1227
 
1228 1228
 static void check_user_password(struct pdf_struct *pdf, int R, const char *O,
1229 1229
 				const char *U, int32_t P, int EM,
1230
+				const char *UE,
1230 1231
 				unsigned length, unsigned oulen)
1231 1232
 {
1232 1233
     unsigned i;
... ...
@@ -1248,8 +1673,24 @@ static void check_user_password(struct pdf_struct *pdf, int R, const char *O,
1248 1248
 	sha256_final(&sha256, result2);
1249 1249
 	dbg_printhex("Computed U", result2, 32);
1250 1250
 	if (!memcmp(result2, U, 32)) {
1251
+	    off_t n;
1251 1252
 	    password_empty = 1;
1252 1253
 	    /* Algorithm 3.2a could be used to recover encryption key */
1254
+	    sha256_init(&sha256);
1255
+	    sha256_update(&sha256, U+40, 8);
1256
+	    sha256_final(&sha256, result2);
1257
+	    n = UE ? strlen(UE) : 0;
1258
+	    if (n != 32) {
1259
+		cli_dbgmsg("cli_pdf: UE length is not 32: %d\n", n);
1260
+		noisy_warnmsg("cli_pdf: UE length is not 32: %d\n", n);
1261
+	    } else {
1262
+		pdf->keylen = 32;
1263
+		pdf->key = cli_malloc(32);
1264
+		if (!pdf->key)
1265
+		    return;
1266
+		aes_decrypt(UE, &n, pdf->key, result2, 32, 0);
1267
+		dbg_printhex("cli_pdf: Candidate encryption key", pdf->key, pdf->keylen);
1268
+	    }
1253 1269
 	}
1254 1270
     } else {
1255 1271
 	/* 7.6.3.3 Algorithm 2 */
... ...
@@ -1281,7 +1722,7 @@ static void check_user_password(struct pdf_struct *pdf, int R, const char *O,
1281 1281
 	if (!pdf->key)
1282 1282
 	    return;
1283 1283
 	memcpy(pdf->key, result, pdf->keylen);
1284
-	dbg_printhex("md5", result, 32);
1284
+	dbg_printhex("md5", result, 16);
1285 1285
 	dbg_printhex("Candidate encryption key", pdf->key, pdf->keylen);
1286 1286
 
1287 1287
 	/* 7.6.3.3 Algorithm 6 */
... ...
@@ -1316,53 +1757,89 @@ static void check_user_password(struct pdf_struct *pdf, int R, const char *O,
1316 1316
 		password_empty = 1;
1317 1317
 	} else {
1318 1318
 	    cli_dbgmsg("cli_pdf: invalid revision %d\n", R);
1319
+	    noisy_warnmsg("cli_pdf: invalid revision %d\n", R);
1319 1320
 	}
1320 1321
     }
1321 1322
     if (password_empty) {
1322 1323
 	cli_dbgmsg("cli_pdf: user password is empty\n");
1324
+	noisy_msg(pdf, "cli_pdf: encrypted PDF found, user password is empty, will attempt to decrypt\n");
1323 1325
 	/* The key we computed above is the key used to encrypt the streams.
1324 1326
 	 * We could decrypt it now if we wanted to */
1325 1327
 	pdf->flags |= 1 << DECRYPTABLE_PDF;
1326 1328
     } else {
1327 1329
 	cli_dbgmsg("cli_pdf: user/owner password would be required for decryption\n");
1330
+	noisy_warnmsg("cli_pdf: encrypted PDF found, user password is NOT empty, cannot decrypt!\n");
1328 1331
 	/* the key is not valid, we would need the user or the owner password to
1329 1332
 	 * decrypt */
1330 1333
     }
1331 1334
 }
1332 1335
 
1336
+static enum enc_method parse_enc_method(const char *dict, unsigned len, const char *key, enum enc_method def)
1337
+{
1338
+    const char *q;
1339
+    char *CFM = NULL;
1340
+    if (!key)
1341
+	return def;
1342
+    if (!strcmp(key, "Identity"))
1343
+	return ENC_IDENTITY;
1344
+    q = pdf_getdict(dict, &len, key);
1345
+    if (!q)
1346
+	return def;
1347
+    CFM = pdf_readval(q, len, "/CFM");
1348
+    if (CFM) {
1349
+	cli_dbgmsg("cli_pdf: %s CFM: %s\n", key, CFM);
1350
+	if (!strncmp(CFM,"V2", 2))
1351
+	    return ENC_V2;
1352
+	if (!strncmp(CFM,"AESV2",5))
1353
+	    return ENC_AESV2;
1354
+	if (!strncmp(CFM,"AESV3",5))
1355
+	    return ENC_AESV3;
1356
+	if (!strncmp(CFM,"None",4))
1357
+	    return ENC_NONE;
1358
+    }
1359
+    return ENC_UNKNOWN;
1360
+}
1361
+
1333 1362
 static void pdf_handle_enc(struct pdf_struct *pdf)
1334 1363
 {
1335 1364
     struct pdf_obj *obj;
1336
-    uint32_t len, required_flags, n, R, P, length, EM, i, oulen;
1337
-    char *O, *U;
1365
+    uint32_t len, required_flags, n, R, P, length, EM = 1, i, oulen;
1366
+    char *O, *U, *UE, *StmF, *StrF, *EFF;
1338 1367
     const char *q, *q2;
1339 1368
 
1340 1369
     if (pdf->enc_objid == ~0u)
1341 1370
 	return;
1342 1371
     if (!pdf->fileID) {
1343 1372
 	cli_dbgmsg("cli_pdf: pdf_handle_enc no file ID\n");
1373
+	noisy_warnmsg("cli_pdf: pdf_handle_enc no file ID\n");
1344 1374
 	return;
1345 1375
     }
1346 1376
     obj = find_obj(pdf, pdf->objs, pdf->enc_objid);
1347 1377
     if (!obj) {
1348 1378
 	cli_dbgmsg("cli_pdf: can't find encrypted object %d %d\n", pdf->enc_objid>>8, pdf->enc_objid&0xff);
1379
+	noisy_warnmsg("cli_pdf: can't find encrypted object %d %d\n", pdf->enc_objid>>8, pdf->enc_objid&0xff);
1349 1380
 	return;
1350 1381
     }
1351 1382
     len = obj_size(pdf, obj, 1);
1352 1383
     q = pdf->map + obj->start;
1353 1384
 
1354
-    O = U = NULL;
1385
+    O = U = UE = StmF = StrF = EFF = NULL;
1355 1386
     do {
1356
-	EM = pdf_readbool(q, len, "/EncryptMetadata", 1);
1387
+
1388
+	pdf->enc_method_string = ENC_UNKNOWN;
1389
+	pdf->enc_method_stream = ENC_UNKNOWN;
1390
+	pdf->enc_method_embeddedfile = ENC_UNKNOWN;
1357 1391
 	P = pdf_readint(q, len, "/P");
1358 1392
 	if (P == ~0u) {
1359 1393
 	    cli_dbgmsg("cli_pdf: invalid P\n");
1394
+	    noisy_warnmsg("cli_pdf: invalid P\n");
1360 1395
 	    break;
1361 1396
 	}
1362 1397
 
1363 1398
 	q2 = cli_memstr(q, len, "/Standard", 9);
1364 1399
 	if (!q2) {
1365 1400
 	    cli_dbgmsg("cli_pdf: /Standard not found\n");
1401
+	    noisy_warnmsg("cli_pdf: /Standard not found\n");
1366 1402
 	    break;
1367 1403
 	}
1368 1404
 	/* we can have both of these:
... ...
@@ -1372,8 +1849,6 @@ static void pdf_handle_enc(struct pdf_struct *pdf)
1372 1372
 	length = pdf_readint(q2, len - (q2 - q), "/Length");
1373 1373
 	if (length == ~0u)
1374 1374
 	    length = pdf_readint(q, len, "/Length");
1375
-	if (length == ~0u)
1376
-	    length = 40;
1377 1375
 	if (length < 40) {
1378 1376
 	    cli_dbgmsg("cli_pdf: invalid length: %d\n", length);
1379 1377
 	    length = 40;
... ...
@@ -1382,6 +1857,7 @@ static void pdf_handle_enc(struct pdf_struct *pdf)
1382 1382
 	R = pdf_readint(q, len, "/R");
1383 1383
 	if (R == ~0u) {
1384 1384
 	    cli_dbgmsg("cli_pdf: invalid R\n");
1385
+	    noisy_warnmsg("cli_pdf: invalid R\n");
1385 1386
 	    break;
1386 1387
 	}
1387 1388
 
... ...
@@ -1389,11 +1865,46 @@ static void pdf_handle_enc(struct pdf_struct *pdf)
1389 1389
 	    oulen = 32;
1390 1390
 	else
1391 1391
 	    oulen = 48;
1392
+	if (R == 2 || R == 3) {
1393
+	    pdf->enc_method_stream = ENC_V2;
1394
+	    pdf->enc_method_string = ENC_V2;
1395
+	    pdf->enc_method_embeddedfile = ENC_V2;
1396
+	} else if (R == 4 || R == 5) {
1397
+	    EM = pdf_readbool(q, len, "/EncryptMetadata", 1);
1398
+	    StmF = pdf_readval(q, len, "/StmF");
1399
+	    StrF = pdf_readval(q, len, "/StrF");
1400
+	    EFF = pdf_readval(q, len, "/EFF");
1401
+	    n = len;
1402
+	    pdf->CF = pdf_getdict(q, &n, "/CF");
1403
+	    pdf->CF_n = n;
1404
+	    if (StmF)
1405
+		cli_dbgmsg("cli_pdf: StmF: %s\n", StmF);
1406
+	    if (StrF)
1407
+		cli_dbgmsg("cli_pdf: StrF: %s\n", StrF);
1408
+	    if (EFF)
1409
+		cli_dbgmsg("cli_pdf: EFF: %s\n", EFF);
1410
+	    pdf->enc_method_stream = parse_enc_method(pdf->CF, n, StmF, ENC_IDENTITY);
1411
+	    pdf->enc_method_string = parse_enc_method(pdf->CF, n, StrF, ENC_IDENTITY);
1412
+	    pdf->enc_method_embeddedfile = parse_enc_method(pdf->CF, n, EFF, pdf->enc_method_stream);
1413
+
1414
+	    cli_dbgmsg("cli_pdf: EncryptMetadata: %s\n",
1415
+		       EM ? "true" : "false");
1416
+	    if (R == 4)
1417
+		length = 128;
1418
+	    else {
1419
+		n = 0;
1420
+		UE = pdf_readstring(q, len, "/UE", &n);
1421
+		length = 256;
1422
+	    }
1423
+	}
1424
+	if (length == ~0u)
1425
+	    length = 40;
1392 1426
 
1393 1427
 	n = 0;
1394 1428
 	O = pdf_readstring(q, len, "/O", &n);
1395 1429
 	if (!O || n < oulen) {
1396 1430
 	    cli_dbgmsg("cli_pdf: invalid O: %d\n", n);
1431
+	    cli_dbgmsg("cli_pdf: invalid O: %d\n", n);
1397 1432
 	    if (O)
1398 1433
 		dbg_printhex("invalid O", O, n);
1399 1434
 	    break;
... ...
@@ -1404,6 +1915,7 @@ static void pdf_handle_enc(struct pdf_struct *pdf)
1404 1404
 		    break;
1405 1405
 	    if (i != n) {
1406 1406
 		dbg_printhex("too long O", O, n);
1407
+		noisy_warnmsg("too long O", O, n);
1407 1408
 		break;
1408 1409
 	    }
1409 1410
 	}
... ...
@@ -1412,6 +1924,7 @@ static void pdf_handle_enc(struct pdf_struct *pdf)
1412 1412
 	U = pdf_readstring(q, len, "/U", &n);
1413 1413
 	if (!U || n < oulen) {
1414 1414
 	    cli_dbgmsg("cli_pdf: invalid U: %d\n", n);
1415
+	    noisy_warnmsg("cli_pdf: invalid U: %d\n", n);
1415 1416
 	    if (U)
1416 1417
 		dbg_printhex("invalid U", U, n);
1417 1418
 	    break;
... ...
@@ -1428,12 +1941,14 @@ static void pdf_handle_enc(struct pdf_struct *pdf)
1428 1428
 	cli_dbgmsg("cli_pdf: Encrypt R: %d, P %x, length: %d\n", R, P, length);
1429 1429
 	if (length % 8) {
1430 1430
 	    cli_dbgmsg("cli_pdf: wrong key length, not multiple of 8\n");
1431
+	    noisy_warnmsg("cli_pdf: wrong key length, not multiple of 8\n");
1431 1432
 	    break;
1432 1433
 	}
1433
-	check_user_password(pdf, R, O, U, P, EM, length, oulen);
1434
+	check_user_password(pdf, R, O, U, P, EM, UE, length, oulen);
1434 1435
     } while (0);
1435 1436
     free(O);
1436 1437
     free(U);
1438
+    free(UE);
1437 1439
 }
1438 1440
 
1439 1441
 int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
... ...
@@ -1465,6 +1980,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
1465 1465
     pdfver = cli_memstr(pdfver, versize, "%PDF-", 5);
1466 1466
     if (!pdfver) {
1467 1467
 	cli_dbgmsg("cli_pdf: no PDF- header found\n");
1468
+	noisy_warnmsg("cli_pdf: no PDF- header found\n");
1468 1469
 	return CL_SUCCESS;
1469 1470
     }
1470 1471
     /* Check for PDF-1.[0-9]. Although 1.7 is highest now, allow for future
... ...
@@ -1510,19 +2026,12 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
1510 1510
 	    pdf.flags |= 1 << BAD_PDF_TRAILER;
1511 1511
 	    cli_dbgmsg("cli_pdf: startxref not found\n");
1512 1512
 	} else {
1513
-	    const char *enc;
1514 1513
 	    for (t=q;t > eofmap; t--) {
1515 1514
 		if (memcmp(t,"trailer",7) == 0)
1516 1515
 		    break;
1517 1516
 	    }
1518 1517
 
1519
-	    enc = cli_memstr(eofmap, bytesleft, "/Encrypt", 8);
1520
-	    if (enc) {
1521
-		pdf.flags |= 1 << ENCRYPTED_PDF;
1522
-		cli_dbgmsg("cli_pdf: encrypted pdf found, stream will probably fail to decompress!\n");
1523
-		pdf_parse_encrypt(&pdf, enc, eof - enc);
1524
-		pdf.fileID = pdf_readstring(eofmap, bytesleft, "/ID", &pdf.fileIDlen);
1525
-	    }
1518
+	    pdf_parse_trailer(&pdf, eofmap, eof - eofmap);
1526 1519
 	    q += 9;
1527 1520
 	    while (q < eof && (*q == ' ' || *q == '\n' || *q == '\r')) { q++; }
1528 1521
 	    xref = atol(q);
... ...
@@ -1553,7 +2062,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
1553 1553
     /* parse PDF and find obj offsets */
1554 1554
     while ((rc = pdf_findobj(&pdf)) > 0) {
1555 1555
 	struct pdf_obj *obj = &pdf.objs[pdf.nobjs-1];
1556
-	cli_dbgmsg("found %d %d obj @%ld\n", obj->id >> 8, obj->id&0xff, obj->start + offset);
1556
+	cli_dbgmsg("cli_pdf: found %d %d obj @%ld\n", obj->id >> 8, obj->id&0xff, obj->start + offset);
1557 1557
     }
1558 1558
     if (pdf.nobjs)
1559 1559
 	pdf.nobjs--;
... ...
@@ -1567,6 +2076,10 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
1567 1567
     }
1568 1568
 
1569 1569
     pdf_handle_enc(&pdf);
1570
+    if (pdf.flags & (1 << ENCRYPTED_PDF))
1571
+	cli_dbgmsg("cli_pdf: encrypted pdf found, %s!\n",
1572
+		   (pdf.flags & (1 << DECRYPTABLE_PDF)) ?
1573
+		   "decryptable" : "not decryptable, stream will probably fail to decompress");
1570 1574
 
1571 1575
     if (DETECT_ENCRYPTED &&
1572 1576
 	(pdf.flags & (1 << ENCRYPTED_PDF)) &&
... ...
@@ -2276,7 +2789,7 @@ ascii85decode(const char *buf, off_t len, unsigned char *output)
2276 2276
 			}
2277 2277
 		} else if(byte == 'z') {
2278 2278
 			if(quintet) {
2279
-				cli_dbgmsg("ascii85decode: unexpected 'z'\n");
2279
+				cli_dbgmsg("cli_pdf: ascii85decode: unexpected 'z'\n");
2280 2280
 				return -1;
2281 2281
 			}
2282 2282
 			*output++ = '\0';
... ...
@@ -2285,12 +2798,12 @@ ascii85decode(const char *buf, off_t len, unsigned char *output)
2285 2285
 			*output++ = '\0';
2286 2286
 			ret += 4;
2287 2287
 		} else if(byte == EOF) {
2288
-			cli_dbgmsg("ascii85decode: quintet %d\n", quintet);
2288
+			cli_dbgmsg("cli_pdf: ascii85decode: quintet %d\n", quintet);
2289 2289
 			if(quintet) {
2290 2290
 				int i;
2291 2291
 
2292 2292
 				if(quintet == 1) {
2293
-					cli_dbgmsg("ascii85Decode: only 1 byte in last quintet\n");
2293
+					cli_dbgmsg("cli_pdf: ascii85Decode: only 1 byte in last quintet\n");
2294 2294
 					return -1;
2295 2295
 				}
2296 2296
 				for(i = quintet; i < 5; i++)
... ...
@@ -2304,7 +2817,7 @@ ascii85decode(const char *buf, off_t len, unsigned char *output)
2304 2304
 			}
2305 2305
 			break;
2306 2306
 		} else if(!isspace(byte)) {
2307
-			cli_dbgmsg("ascii85Decode: invalid character 0x%x, len %lu\n",
2307
+			cli_dbgmsg("cli_pdf: ascii85Decode: invalid character 0x%x, len %lu\n",
2308 2308
 				byte & 0xFF, (unsigned long)len);
2309 2309
 			return -1;
2310 2310
 		}
2311 2311
new file mode 100644
... ...
@@ -0,0 +1,1208 @@
0
+/* public domain code from http://www.efgh.com/software/rijndael.htm */
1
+#define FULL_UNROLL
2
+
3
+#include "rijndael.h"
4
+
5
+typedef unsigned long u32;
6
+typedef unsigned char u8;
7
+
8
+static const u32 Te0[256] =
9
+{
10
+  0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
11
+  0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
12
+  0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
13
+  0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
14
+  0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
15
+  0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
16
+  0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
17
+  0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
18
+  0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
19
+  0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
20
+  0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
21
+  0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
22
+  0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
23
+  0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
24
+  0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
25
+  0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
26
+  0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
27
+  0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
28
+  0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
29
+  0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
30
+  0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
31
+  0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
32
+  0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
33
+  0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
34
+  0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
35
+  0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
36
+  0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
37
+  0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
38
+  0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
39
+  0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
40
+  0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
41
+  0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
42
+  0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
43
+  0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
44
+  0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
45
+  0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
46
+  0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
47
+  0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
48
+  0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
49
+  0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
50
+  0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
51
+  0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
52
+  0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
53
+  0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
54
+  0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
55
+  0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
56
+  0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
57
+  0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
58
+  0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
59
+  0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
60
+  0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
61
+  0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
62
+  0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
63
+  0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
64
+  0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
65
+  0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
66
+  0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
67
+  0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
68
+  0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
69
+  0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
70
+  0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
71
+  0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
72
+  0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
73
+  0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
74
+};
75
+
76
+static const u32 Te1[256] =
77
+{
78
+  0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
79
+  0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
80
+  0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
81
+  0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
82
+  0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
83
+  0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
84
+  0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
85
+  0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
86
+  0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
87
+  0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
88
+  0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
89
+  0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
90
+  0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
91
+  0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
92
+  0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
93
+  0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
94
+  0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
95
+  0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
96
+  0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
97
+  0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
98
+  0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
99
+  0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
100
+  0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
101
+  0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
102
+  0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
103
+  0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
104
+  0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
105
+  0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
106
+  0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
107
+  0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
108
+  0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
109
+  0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
110
+  0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
111
+  0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
112
+  0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
113
+  0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
114
+  0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
115
+  0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
116
+  0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
117
+  0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
118
+  0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
119
+  0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
120
+  0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
121
+  0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
122
+  0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
123
+  0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
124
+  0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
125
+  0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
126
+  0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
127
+  0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
128
+  0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
129
+  0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
130
+  0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
131
+  0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
132
+  0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
133
+  0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
134
+  0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
135
+  0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
136
+  0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
137
+  0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
138
+  0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
139
+  0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
140
+  0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
141
+  0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
142
+};
143
+
144
+static const u32 Te2[256] =
145
+{
146
+  0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
147
+  0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
148
+  0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
149
+  0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
150
+  0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
151
+  0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
152
+  0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
153
+  0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
154
+  0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
155
+  0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
156
+  0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
157
+  0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
158
+  0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
159
+  0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
160
+  0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
161
+  0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
162
+  0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
163
+  0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
164
+  0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
165
+  0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
166
+  0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
167
+  0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
168
+  0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
169
+  0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
170
+  0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
171
+  0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
172
+  0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
173
+  0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
174
+  0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
175
+  0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
176
+  0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
177
+  0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
178
+  0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
179
+  0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
180
+  0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
181
+  0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
182
+  0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
183
+  0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
184
+  0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
185
+  0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
186
+  0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
187
+  0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
188
+  0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
189
+  0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
190
+  0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
191
+  0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
192
+  0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
193
+  0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
194
+  0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
195
+  0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
196
+  0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
197
+  0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
198
+  0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
199
+  0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
200
+  0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
201
+  0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
202
+  0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
203
+  0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
204
+  0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
205
+  0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
206
+  0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
207
+  0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
208
+  0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
209
+  0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
210
+};
211
+
212
+static const u32 Te3[256] =
213
+{
214
+  0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
215
+  0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
216
+  0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
217
+  0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
218
+  0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
219
+  0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
220
+  0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
221
+  0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
222
+  0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
223
+  0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
224
+  0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
225
+  0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
226
+  0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
227
+  0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
228
+  0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
229
+  0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
230
+  0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
231
+  0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
232
+  0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
233
+  0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
234
+  0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
235
+  0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
236
+  0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
237
+  0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
238
+  0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
239
+  0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
240
+  0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
241
+  0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
242
+  0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
243
+  0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
244
+  0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
245
+  0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
246
+  0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
247
+  0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
248
+  0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
249
+  0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
250
+  0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
251
+  0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
252
+  0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
253
+  0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
254
+  0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
255
+  0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
256
+  0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
257
+  0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
258
+  0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
259
+  0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
260
+  0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
261
+  0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
262
+  0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
263
+  0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
264
+  0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
265
+  0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
266
+  0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
267
+  0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
268
+  0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
269
+  0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
270
+  0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
271
+  0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
272
+  0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
273
+  0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
274
+  0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
275
+  0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
276
+  0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
277
+  0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
278
+};
279
+
280
+static const u32 Te4[256] =
281
+{
282
+  0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
283
+  0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
284
+  0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
285
+  0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
286
+  0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
287
+  0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
288
+  0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
289
+  0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
290
+  0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
291
+  0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
292
+  0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
293
+  0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
294
+  0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
295
+  0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
296
+  0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
297
+  0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
298
+  0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
299
+  0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
300
+  0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
301
+  0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
302
+  0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
303
+  0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
304
+  0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
305
+  0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
306
+  0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
307
+  0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
308
+  0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
309
+  0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
310
+  0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
311
+  0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
312
+  0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
313
+  0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
314
+  0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
315
+  0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
316
+  0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
317
+  0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
318
+  0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
319
+  0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
320
+  0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
321
+  0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
322
+  0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
323
+  0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
324
+  0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
325
+  0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
326
+  0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
327
+  0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
328
+  0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
329
+  0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
330
+  0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
331
+  0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
332
+  0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
333
+  0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
334
+  0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
335
+  0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
336
+  0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
337
+  0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
338
+  0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
339
+  0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
340
+  0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
341
+  0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
342
+  0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
343
+  0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
344
+  0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
345
+  0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
346
+};
347
+
348
+static const u32 Td0[256] =
349
+{
350
+  0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
351
+  0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
352
+  0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
353
+  0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
354
+  0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
355
+  0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
356
+  0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
357
+  0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
358
+  0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
359
+  0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
360
+  0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
361
+  0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
362
+  0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
363
+  0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
364
+  0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
365
+  0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
366
+  0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
367
+  0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
368
+  0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
369
+  0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
370
+  0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
371
+  0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
372
+  0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
373
+  0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
374
+  0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
375
+  0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
376
+  0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
377
+  0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
378
+  0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
379
+  0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
380
+  0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
381
+  0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
382
+  0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
383
+  0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
384
+  0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
385
+  0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
386
+  0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
387
+  0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
388
+  0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
389
+  0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
390
+  0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
391
+  0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
392
+  0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
393
+  0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
394
+  0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
395
+  0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
396
+  0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
397
+  0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
398
+  0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
399
+  0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
400
+  0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
401
+  0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
402
+  0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
403
+  0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
404
+  0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
405
+  0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
406
+  0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
407
+  0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
408
+  0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
409
+  0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
410
+  0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
411
+  0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
412
+  0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
413
+  0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
414
+};
415
+
416
+static const u32 Td1[256] =
417
+{
418
+  0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
419
+  0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
420
+  0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
421
+  0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
422
+  0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
423
+  0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
424
+  0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
425
+  0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
426
+  0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
427
+  0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
428
+  0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
429
+  0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
430
+  0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
431
+  0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
432
+  0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
433
+  0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
434
+  0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
435
+  0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
436
+  0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
437
+  0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
438
+  0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
439
+  0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
440
+  0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
441
+  0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
442
+  0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
443
+  0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
444
+  0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
445
+  0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
446
+  0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
447
+  0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
448
+  0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
449
+  0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
450
+  0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
451
+  0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
452
+  0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
453
+  0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
454
+  0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
455
+  0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
456
+  0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
457
+  0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
458
+  0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
459
+  0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
460
+  0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
461
+  0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
462
+  0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
463
+  0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
464
+  0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
465
+  0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
466
+  0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
467
+  0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
468
+  0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
469
+  0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
470
+  0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
471
+  0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
472
+  0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
473
+  0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
474
+  0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
475
+  0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
476
+  0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
477
+  0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
478
+  0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
479
+  0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
480
+  0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
481
+  0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
482
+};
483
+
484
+static const u32 Td2[256] =
485
+{
486
+  0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
487
+  0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
488
+  0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
489
+  0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
490
+  0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
491
+  0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
492
+  0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
493
+  0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
494
+  0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
495
+  0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
496
+  0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
497
+  0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
498
+  0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
499
+  0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
500
+  0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
501
+  0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
502
+  0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
503
+  0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
504
+  0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
505
+  0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
506
+  0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
507
+  0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
508
+  0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
509
+  0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
510
+  0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
511
+  0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
512
+  0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
513
+  0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
514
+  0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
515
+  0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
516
+  0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
517
+  0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
518
+  0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
519
+  0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
520
+  0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
521
+  0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
522
+  0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
523
+  0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
524
+  0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
525
+  0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
526
+  0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
527
+  0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
528
+  0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
529
+  0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
530
+  0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
531
+  0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
532
+  0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
533
+  0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
534
+  0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
535
+  0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
536
+  0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
537
+  0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
538
+  0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
539
+  0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
540
+  0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
541
+  0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
542
+  0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
543
+  0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
544
+  0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
545
+  0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
546
+  0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
547
+  0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
548
+  0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
549
+  0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
550
+};
551
+
552
+static const u32 Td3[256] =
553
+{
554
+  0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
555
+  0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
556
+  0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
557
+  0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
558
+  0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
559
+  0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
560
+  0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
561
+  0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
562
+  0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
563
+  0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
564
+  0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
565
+  0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
566
+  0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
567
+  0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
568
+  0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
569
+  0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
570
+  0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
571
+  0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
572
+  0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
573
+  0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
574
+  0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
575
+  0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
576
+  0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
577
+  0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
578
+  0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
579
+  0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
580
+  0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
581
+  0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
582
+  0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
583
+  0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
584
+  0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
585
+  0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
586
+  0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
587
+  0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
588
+  0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
589
+  0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
590
+  0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
591
+  0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
592
+  0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
593
+  0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
594
+  0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
595
+  0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
596
+  0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
597
+  0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
598
+  0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
599
+  0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
600
+  0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
601
+  0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
602
+  0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
603
+  0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
604
+  0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
605
+  0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
606
+  0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
607
+  0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
608
+  0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
609
+  0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
610
+  0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
611
+  0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
612
+  0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
613
+  0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
614
+  0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
615
+  0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
616
+  0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
617
+  0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
618
+};
619
+
620
+static const u32 Td4[256] =
621
+{
622
+  0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
623
+  0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
624
+  0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
625
+  0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
626
+  0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
627
+  0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
628
+  0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
629
+  0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
630
+  0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
631
+  0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
632
+  0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
633
+  0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
634
+  0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
635
+  0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
636
+  0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
637
+  0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
638
+  0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
639
+  0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
640
+  0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
641
+  0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
642
+  0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
643
+  0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
644
+  0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
645
+  0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
646
+  0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
647
+  0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
648
+  0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
649
+  0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
650
+  0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
651
+  0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
652
+  0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
653
+  0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
654
+  0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
655
+  0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
656
+  0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
657
+  0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
658
+  0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
659
+  0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
660
+  0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
661
+  0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
662
+  0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
663
+  0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
664
+  0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
665
+  0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
666
+  0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
667
+  0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
668
+  0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
669
+  0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
670
+  0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
671
+  0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
672
+  0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
673
+  0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
674
+  0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
675
+  0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
676
+  0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
677
+  0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
678
+  0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
679
+  0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
680
+  0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
681
+  0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
682
+  0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
683
+  0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
684
+  0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
685
+  0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
686
+};
687
+
688
+static const u32 rcon[] =
689
+{
690
+  0x01000000, 0x02000000, 0x04000000, 0x08000000,
691
+  0x10000000, 0x20000000, 0x40000000, 0x80000000,
692
+  0x1B000000, 0x36000000,
693
+  /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
694
+};
695
+
696
+#define GETU32(plaintext) (((u32)(plaintext)[0] << 24) ^ \
697
+                    ((u32)(plaintext)[1] << 16) ^ \
698
+                    ((u32)(plaintext)[2] <<  8) ^ \
699
+                    ((u32)(plaintext)[3]))
700
+
701
+#define PUTU32(ciphertext, st) { (ciphertext)[0] = (u8)((st) >> 24); \
702
+                         (ciphertext)[1] = (u8)((st) >> 16); \
703
+                         (ciphertext)[2] = (u8)((st) >>  8); \
704
+                         (ciphertext)[3] = (u8)(st); }
705
+
706
+/**
707
+ * Expand the cipher key into the encryption key schedule.
708
+ *
709
+ * @return the number of rounds for the given cipher key size.
710
+ */
711
+int rijndaelSetupEncrypt(u32 *rk, const u8 *key, int keybits)
712
+{
713
+  int i = 0;
714
+  u32 temp;
715
+
716
+  rk[0] = GETU32(key     );
717
+  rk[1] = GETU32(key +  4);
718
+  rk[2] = GETU32(key +  8);
719
+  rk[3] = GETU32(key + 12);
720
+  if (keybits == 128)
721
+  {
722
+    for (;;)
723
+    {
724
+      temp  = rk[3];
725
+      rk[4] = rk[0] ^
726
+        (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
727
+        (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
728
+        (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
729
+        (Te4[(temp >> 24)       ] & 0x000000ff) ^
730
+        rcon[i];
731
+      rk[5] = rk[1] ^ rk[4];
732
+      rk[6] = rk[2] ^ rk[5];
733
+      rk[7] = rk[3] ^ rk[6];
734
+      if (++i == 10)
735
+        return 10;
736
+      rk += 4;
737
+    }
738
+  }
739
+  rk[4] = GETU32(key + 16);
740
+  rk[5] = GETU32(key + 20);
741
+  if (keybits == 192)
742
+  {
743
+    for (;;)
744
+    {
745
+      temp = rk[ 5];
746
+      rk[ 6] = rk[ 0] ^
747
+        (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
748
+        (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
749
+        (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
750
+        (Te4[(temp >> 24)       ] & 0x000000ff) ^
751
+        rcon[i];
752
+      rk[ 7] = rk[ 1] ^ rk[ 6];
753
+      rk[ 8] = rk[ 2] ^ rk[ 7];
754
+      rk[ 9] = rk[ 3] ^ rk[ 8];
755
+      if (++i == 8)
756
+        return 12;
757
+      rk[10] = rk[ 4] ^ rk[ 9];
758
+      rk[11] = rk[ 5] ^ rk[10];
759
+      rk += 6;
760
+    }
761
+  }
762
+  rk[6] = GETU32(key + 24);
763
+  rk[7] = GETU32(key + 28);
764
+  if (keybits == 256)
765
+  {
766
+    for (;;)
767
+    {
768
+      temp = rk[ 7];
769
+      rk[ 8] = rk[ 0] ^
770
+        (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
771
+        (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
772
+        (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
773
+        (Te4[(temp >> 24)       ] & 0x000000ff) ^
774
+        rcon[i];
775
+      rk[ 9] = rk[ 1] ^ rk[ 8];
776
+      rk[10] = rk[ 2] ^ rk[ 9];
777
+      rk[11] = rk[ 3] ^ rk[10];
778
+      if (++i == 7)
779
+        return 14;
780
+      temp = rk[11];
781
+      rk[12] = rk[ 4] ^
782
+        (Te4[(temp >> 24)       ] & 0xff000000) ^
783
+        (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
784
+        (Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
785
+        (Te4[(temp      ) & 0xff] & 0x000000ff);
786
+      rk[13] = rk[ 5] ^ rk[12];
787
+      rk[14] = rk[ 6] ^ rk[13];
788
+      rk[15] = rk[ 7] ^ rk[14];
789
+      rk += 8;
790
+    }
791
+  }
792
+  return 0;
793
+}
794
+
795
+/**
796
+ * Expand the cipher key into the decryption key schedule.
797
+ *
798
+ * @return the number of rounds for the given cipher key size.
799
+ */
800
+int rijndaelSetupDecrypt(u32 *rk, const u8 *key, int keybits)
801
+{
802
+  int nrounds, i, j;
803
+  u32 temp;
804
+
805
+  /* expand the cipher key: */
806
+  nrounds = rijndaelSetupEncrypt(rk, key, keybits);
807
+  /* invert the order of the round keys: */
808
+  for (i = 0, j = 4*nrounds; i < j; i += 4, j -= 4)
809
+  {
810
+    temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
811
+    temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
812
+    temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
813
+    temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
814
+  }
815
+  /* apply the inverse MixColumn transform to all round keys but the first and the last: */
816
+  for (i = 1; i < nrounds; i++)
817
+  {
818
+    rk += 4;
819
+    rk[0] =
820
+      Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
821
+      Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
822
+      Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
823
+      Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
824
+    rk[1] =
825
+      Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
826
+      Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
827
+      Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
828
+      Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
829
+    rk[2] =
830
+      Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
831
+      Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
832
+      Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
833
+      Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
834
+    rk[3] =
835
+      Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
836
+      Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
837
+      Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
838
+      Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
839
+  }
840
+  return nrounds;
841
+}
842
+
843
+void rijndaelEncrypt(const u32 *rk, int nrounds, const u8 plaintext[16],
844
+  u8 ciphertext[16])
845
+{
846
+  u32 s0, s1, s2, s3, t0, t1, t2, t3;
847
+  #ifndef FULL_UNROLL
848
+    int r;
849
+  #endif /* ?FULL_UNROLL */
850
+  /*
851
+   * map byte array block to cipher state
852
+   * and add initial round key:
853
+  */
854
+  s0 = GETU32(plaintext     ) ^ rk[0];
855
+  s1 = GETU32(plaintext +  4) ^ rk[1];
856
+  s2 = GETU32(plaintext +  8) ^ rk[2];
857
+  s3 = GETU32(plaintext + 12) ^ rk[3];
858
+  #ifdef FULL_UNROLL
859
+    /* round 1: */
860
+    t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
861
+    t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
862
+    t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
863
+    t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
864
+    /* round 2: */
865
+    s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
866
+    s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
867
+    s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
868
+    s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
869
+    /* round 3: */
870
+    t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
871
+    t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
872
+    t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
873
+    t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
874
+    /* round 4: */
875
+    s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
876
+    s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
877
+    s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
878
+    s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
879
+    /* round 5: */
880
+    t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
881
+    t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
882
+    t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
883
+    t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
884
+    /* round 6: */
885
+    s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
886
+    s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
887
+    s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
888
+    s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
889
+    /* round 7: */
890
+    t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
891
+    t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
892
+    t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
893
+    t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
894
+    /* round 8: */
895
+    s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
896
+    s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
897
+    s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
898
+    s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
899
+    /* round 9: */
900
+    t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
901
+    t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
902
+    t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
903
+    t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
904
+    if (nrounds > 10)
905
+    {
906
+      /* round 10: */
907
+      s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
908
+      s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
909
+      s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
910
+      s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
911
+      /* round 11: */
912
+      t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
913
+      t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
914
+      t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
915
+      t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
916
+      if (nrounds > 12)
917
+      {
918
+        /* round 12: */
919
+        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
920
+        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
921
+        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
922
+        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
923
+        /* round 13: */
924
+        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
925
+        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
926
+        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
927
+        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
928
+      }
929
+    }
930
+    rk += nrounds << 2;
931
+  #else  /* !FULL_UNROLL */
932
+    /*
933
+    * nrounds - 1 full rounds:
934
+    */
935
+    r = nrounds >> 1;
936
+    for (;;)
937
+    {
938
+      t0 =
939
+        Te0[(s0 >> 24)       ] ^
940
+        Te1[(s1 >> 16) & 0xff] ^
941
+        Te2[(s2 >>  8) & 0xff] ^
942
+        Te3[(s3      ) & 0xff] ^
943
+        rk[4];
944
+      t1 =
945
+        Te0[(s1 >> 24)       ] ^
946
+        Te1[(s2 >> 16) & 0xff] ^
947
+        Te2[(s3 >>  8) & 0xff] ^
948
+        Te3[(s0      ) & 0xff] ^
949
+        rk[5];
950
+      t2 =
951
+        Te0[(s2 >> 24)       ] ^
952
+        Te1[(s3 >> 16) & 0xff] ^
953
+        Te2[(s0 >>  8) & 0xff] ^
954
+        Te3[(s1      ) & 0xff] ^
955
+        rk[6];
956
+      t3 =
957
+        Te0[(s3 >> 24)       ] ^
958
+        Te1[(s0 >> 16) & 0xff] ^
959
+        Te2[(s1 >>  8) & 0xff] ^
960
+        Te3[(s2      ) & 0xff] ^
961
+        rk[7];
962
+        rk += 8;
963
+        if (--r == 0)
964
+            break;
965
+      s0 =
966
+        Te0[(t0 >> 24)       ] ^
967
+        Te1[(t1 >> 16) & 0xff] ^
968
+        Te2[(t2 >>  8) & 0xff] ^
969
+        Te3[(t3      ) & 0xff] ^
970
+        rk[0];
971
+      s1 =
972
+        Te0[(t1 >> 24)       ] ^
973
+        Te1[(t2 >> 16) & 0xff] ^
974
+        Te2[(t3 >>  8) & 0xff] ^
975
+        Te3[(t0      ) & 0xff] ^
976
+        rk[1];
977
+      s2 =
978
+        Te0[(t2 >> 24)       ] ^
979
+        Te1[(t3 >> 16) & 0xff] ^
980
+        Te2[(t0 >>  8) & 0xff] ^
981
+        Te3[(t1      ) & 0xff] ^
982
+        rk[2];
983
+      s3 =
984
+        Te0[(t3 >> 24)       ] ^
985
+        Te1[(t0 >> 16) & 0xff] ^
986
+        Te2[(t1 >>  8) & 0xff] ^
987
+        Te3[(t2      ) & 0xff] ^
988
+        rk[3];
989
+     }
990
+ #endif /* ?FULL_UNROLL */
991
+  /*
992
+  * apply last round and
993
+  * map cipher state to byte array block:
994
+  */
995
+  s0 =
996
+    (Te4[(t0 >> 24)       ] & 0xff000000) ^
997
+    (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
998
+    (Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
999
+    (Te4[(t3      ) & 0xff] & 0x000000ff) ^
1000
+    rk[0];
1001
+  PUTU32(ciphertext     , s0);
1002
+  s1 =
1003
+    (Te4[(t1 >> 24)       ] & 0xff000000) ^
1004
+    (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
1005
+    (Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
1006
+    (Te4[(t0      ) & 0xff] & 0x000000ff) ^
1007
+    rk[1];
1008
+  PUTU32(ciphertext +  4, s1);
1009
+  s2 =
1010
+    (Te4[(t2 >> 24)       ] & 0xff000000) ^
1011
+    (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
1012
+    (Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
1013
+    (Te4[(t1      ) & 0xff] & 0x000000ff) ^
1014
+    rk[2];
1015
+  PUTU32(ciphertext +  8, s2);
1016
+  s3 =
1017
+    (Te4[(t3 >> 24)       ] & 0xff000000) ^
1018
+    (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
1019
+    (Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
1020
+    (Te4[(t2      ) & 0xff] & 0x000000ff) ^
1021
+    rk[3];
1022
+  PUTU32(ciphertext + 12, s3);
1023
+}
1024
+
1025
+void rijndaelDecrypt(const u32 *rk, int nrounds, const u8 ciphertext[16],
1026
+  u8 plaintext[16])
1027
+{
1028
+  u32 s0, s1, s2, s3, t0, t1, t2, t3;
1029
+  #ifndef FULL_UNROLL
1030
+    int r;
1031
+  #endif /* ?FULL_UNROLL */
1032
+
1033
+  /*
1034
+  * map byte array block to cipher state
1035
+  * and add initial round key:
1036
+  */
1037
+    s0 = GETU32(ciphertext     ) ^ rk[0];
1038
+    s1 = GETU32(ciphertext +  4) ^ rk[1];
1039
+    s2 = GETU32(ciphertext +  8) ^ rk[2];
1040
+    s3 = GETU32(ciphertext + 12) ^ rk[3];
1041
+  #ifdef FULL_UNROLL
1042
+    /* round 1: */
1043
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
1044
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
1045
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
1046
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
1047
+    /* round 2: */
1048
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
1049
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
1050
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
1051
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
1052
+    /* round 3: */
1053
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
1054
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
1055
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
1056
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
1057
+    /* round 4: */
1058
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
1059
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
1060
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
1061
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
1062
+    /* round 5: */
1063
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
1064
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
1065
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
1066
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
1067
+    /* round 6: */
1068
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
1069
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
1070
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
1071
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
1072
+    /* round 7: */
1073
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
1074
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
1075
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
1076
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
1077
+    /* round 8: */
1078
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
1079
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
1080
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
1081
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
1082
+    /* round 9: */
1083
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
1084
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
1085
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
1086
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
1087
+    if (nrounds > 10)
1088
+    {
1089
+      /* round 10: */
1090
+      s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
1091
+      s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
1092
+      s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
1093
+      s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
1094
+      /* round 11: */
1095
+      t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
1096
+      t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
1097
+      t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
1098
+      t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
1099
+      if (nrounds > 12)
1100
+      {
1101
+        /* round 12: */
1102
+        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
1103
+        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
1104
+        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
1105
+        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
1106
+        /* round 13: */
1107
+        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
1108
+        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
1109
+        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
1110
+        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
1111
+      }
1112
+    }
1113
+    rk += nrounds << 2;
1114
+  #else  /* !FULL_UNROLL */
1115
+    /*
1116
+    * nrounds - 1 full rounds:
1117
+    */
1118
+    r = nrounds >> 1;
1119
+    for (;;)
1120
+    {
1121
+      t0 =
1122
+        Td0[(s0 >> 24)       ] ^
1123
+        Td1[(s3 >> 16) & 0xff] ^
1124
+        Td2[(s2 >>  8) & 0xff] ^
1125
+        Td3[(s1      ) & 0xff] ^
1126
+        rk[4];
1127
+      t1 =
1128
+        Td0[(s1 >> 24)       ] ^
1129
+        Td1[(s0 >> 16) & 0xff] ^
1130
+        Td2[(s3 >>  8) & 0xff] ^
1131
+        Td3[(s2      ) & 0xff] ^
1132
+        rk[5];
1133
+      t2 =
1134
+        Td0[(s2 >> 24)       ] ^
1135
+        Td1[(s1 >> 16) & 0xff] ^
1136
+        Td2[(s0 >>  8) & 0xff] ^
1137
+        Td3[(s3      ) & 0xff] ^
1138
+        rk[6];
1139
+      t3 =
1140
+        Td0[(s3 >> 24)       ] ^
1141
+        Td1[(s2 >> 16) & 0xff] ^
1142
+        Td2[(s1 >>  8) & 0xff] ^
1143
+        Td3[(s0      ) & 0xff] ^
1144
+        rk[7];
1145
+      rk += 8;
1146
+      if (--r == 0)
1147
+          break;
1148
+      s0 =
1149
+        Td0[(t0 >> 24)       ] ^
1150
+        Td1[(t3 >> 16) & 0xff] ^
1151
+        Td2[(t2 >>  8) & 0xff] ^
1152
+        Td3[(t1      ) & 0xff] ^
1153
+        rk[0];
1154
+      s1 =
1155
+        Td0[(t1 >> 24)       ] ^
1156
+        Td1[(t0 >> 16) & 0xff] ^
1157
+        Td2[(t3 >>  8) & 0xff] ^
1158
+        Td3[(t2      ) & 0xff] ^
1159
+        rk[1];
1160
+      s2 =
1161
+        Td0[(t2 >> 24)       ] ^
1162
+        Td1[(t1 >> 16) & 0xff] ^
1163
+        Td2[(t0 >>  8) & 0xff] ^
1164
+        Td3[(t3      ) & 0xff] ^
1165
+        rk[2];
1166
+      s3 =
1167
+        Td0[(t3 >> 24)       ] ^
1168
+        Td1[(t2 >> 16) & 0xff] ^
1169
+        Td2[(t1 >>  8) & 0xff] ^
1170
+        Td3[(t0      ) & 0xff] ^
1171
+        rk[3];
1172
+    }
1173
+  #endif /* ?FULL_UNROLL */
1174
+  /*
1175
+  * apply last round and
1176
+  * map cipher state to byte array block:
1177
+  */
1178
+  s0 =
1179
+    (Td4[(t0 >> 24)       ] & 0xff000000) ^
1180
+    (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
1181
+    (Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
1182
+    (Td4[(t1      ) & 0xff] & 0x000000ff) ^
1183
+    rk[0];
1184
+  PUTU32(plaintext     , s0);
1185
+  s1 =
1186
+    (Td4[(t1 >> 24)       ] & 0xff000000) ^
1187
+    (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
1188
+    (Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
1189
+    (Td4[(t2      ) & 0xff] & 0x000000ff) ^
1190
+    rk[1];
1191
+  PUTU32(plaintext +  4, s1);
1192
+  s2 =
1193
+    (Td4[(t2 >> 24)       ] & 0xff000000) ^
1194
+    (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
1195
+    (Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
1196
+    (Td4[(t3      ) & 0xff] & 0x000000ff) ^
1197
+    rk[2];
1198
+  PUTU32(plaintext +  8, s2);
1199
+  s3 =
1200
+    (Td4[(t3 >> 24)       ] & 0xff000000) ^
1201
+    (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
1202
+    (Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
1203
+    (Td4[(t0      ) & 0xff] & 0x000000ff) ^
1204
+    rk[3];
1205
+  PUTU32(plaintext + 12, s3);
1206
+}
1207
+
0 1208
new file mode 100644
... ...
@@ -0,0 +1,14 @@
0
+#ifndef H__RIJNDAEL
1
+#define H__RIJNDAEL
2
+
3
+int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key,
4
+  int keybits);
5
+void rijndaelDecrypt(const unsigned long *rk, int nrounds,
6
+  const unsigned char ciphertext[16], unsigned char plaintext[16]);
7
+
8
+#define KEYLENGTH(keybits) ((keybits)/8)
9
+#define RKLENGTH(keybits)  ((keybits)/8+28)
10
+#define NROUNDS(keybits)   ((keybits)/32+6)
11
+
12
+#endif
13
+
... ...
@@ -493,24 +493,23 @@ static void cleanup_stack(struct stack* stack,struct rtf_state* state,cli_ctx* c
493 493
 		state.cb_end(&state,ctx);\
494 494
 	tableDestroy(actiontable);\
495 495
 	cleanup_stack(&stack,&state,ctx);\
496
-	free(buff);\
497 496
         if(!ctx->engine->keeptmp)\
498 497
 		cli_rmdirs(tempname);\
499 498
 	free(tempname);\
500 499
 	free(stack.states);
501 500
 
502
-int cli_scanrtf(int desc, cli_ctx *ctx)
501
+int cli_scanrtf(cli_ctx *ctx)
503 502
 {
504 503
 	char* tempname;
505 504
 	const unsigned char* ptr;
506 505
 	const unsigned char* ptr_end;
507
-	unsigned char* buff;
508 506
 	int ret = CL_CLEAN;
509 507
 	struct rtf_state state;
510 508
 	struct stack stack;
511 509
 	ssize_t bread;
512 510
 	table_t* actiontable;
513 511
 	uint8_t main_symbols[256];
512
+	size_t offset = 0;
514 513
 
515 514
 	cli_dbgmsg("in cli_scanrtf()\n");
516 515
 
... ...
@@ -528,19 +527,12 @@ int cli_scanrtf(int desc, cli_ctx *ctx)
528 528
 	if(!stack.states)
529 529
 		return CL_EMEM;
530 530
 
531
-	buff = cli_malloc(BUFF_SIZE);
532
-	if(!buff) {
533
-		free(stack.states);
534
-		return CL_EMEM;
535
-	}
536
-
537 531
 	if(!(tempname = cli_gentemp(ctx->engine->tmpdir)))
538 532
 	    return CL_EMEM;
539 533
 
540 534
 	if(mkdir(tempname, 0700)) {
541 535
 	    	cli_dbgmsg("ScanRTF -> Can't create temporary directory %s\n", tempname);
542 536
 		free(stack.states);
543
-		free(buff);
544 537
 		free(tempname);
545 538
 		return CL_ETMPDIR;
546 539
 	}
... ...
@@ -549,7 +541,6 @@ int cli_scanrtf(int desc, cli_ctx *ctx)
549 549
 	if((ret = load_actions(actiontable))) {
550 550
 		cli_dbgmsg("RTF: Unable to load rtf action table\n");
551 551
 		free(stack.states);
552
-		free(buff);
553 552
 		if(!ctx->engine->keeptmp)
554 553
 			cli_rmdirs(tempname);
555 554
 		free(tempname);
... ...
@@ -559,10 +550,9 @@ int cli_scanrtf(int desc, cli_ctx *ctx)
559 559
 
560 560
 	init_rtf_state(&state);
561 561
 
562
-	while(( bread = cli_readn(desc, buff, BUFF_SIZE) ) > 0) {
563
-		ptr = buff;
564
-		ptr_end = buff + bread;
565
-		while(ptr < ptr_end) {
562
+	for (offset = 0; ptr = fmap_need_off_once_len(*ctx->fmap, offset, BUFF_SIZE, &bread); offset += bread) {
563
+	    ptr_end = ptr + bread;
564
+	    while(ptr < ptr_end) {
566 565
 			switch(state.parse_state) {
567 566
 				case PARSE_MAIN: 
568 567
 					switch(*ptr++) {
... ...
@@ -617,7 +607,7 @@ int cli_scanrtf(int desc, cli_ctx *ctx)
617 617
 							}
618 618
 					}
619 619
 					break;
620
-				case PARSE_CONTROL_:					
620
+				case PARSE_CONTROL_:
621 621
 					if(isalpha(*ptr))  {
622 622
 						state.parse_state = PARSE_CONTROL_WORD;
623 623
 						state.controlword_cnt = 0;
... ...
@@ -23,6 +23,6 @@
23 23
 
24 24
 #include "others.h"
25 25
 
26
-int cli_scanrtf(int desc, cli_ctx *ctx);
26
+int cli_scanrtf(cli_ctx *ctx);
27 27
 
28 28
 #endif
... ...
@@ -86,7 +86,7 @@
86 86
 #include "cpio.h"
87 87
 #include "macho.h"
88 88
 #include "ishield.h"
89
-#include "7z.h"
89
+#include "7z_iface.h"
90 90
 #include "fmap.h"
91 91
 #include "cache.h"
92 92
 #include "events.h"
... ...
@@ -192,7 +192,6 @@ static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx
192 192
 
193 193
     if(DETECT_ENCRYPTED && metadata->encrypted) {
194 194
 	cli_dbgmsg("RAR: Encrypted files found in archive.\n");
195
-	lseek(desc, 0, SEEK_SET);
196 195
 	ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL);
197 196
 	if(ret != CL_VIRUS) {
198 197
 	    *ctx->virname = "Heuristics.Encrypted.RAR";
... ...
@@ -325,7 +324,7 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c
325 325
     return ret;
326 326
 }
327 327
 
328
-static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
328
+static int cli_scanarj(cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_check)
329 329
 {
330 330
 	int ret = CL_CLEAN, rc, file = 0;
331 331
 	arj_metadata_t metadata;
... ...
@@ -343,10 +342,7 @@ static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c
343 343
 	return CL_ETMPDIR;
344 344
     }
345 345
 
346
-    if(sfx_offset)
347
-	lseek(desc, sfx_offset, SEEK_SET);
348
-
349
-    ret = cli_unarj_open(desc, dir);
346
+    ret = cli_unarj_open(*ctx->fmap, dir, &metadata, sfx_offset);
350 347
     if (ret != CL_SUCCESS) {
351 348
 	if(!ctx->engine->keeptmp)
352 349
 	    cli_rmdirs(dir);
... ...
@@ -357,7 +353,7 @@ static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c
357 357
     
358 358
    do {
359 359
         metadata.filename = NULL;
360
-	ret = cli_unarj_prepare_file(desc, dir, &metadata);
360
+	ret = cli_unarj_prepare_file(dir, &metadata);
361 361
 	if (ret != CL_SUCCESS) {
362 362
 	   break;
363 363
 	}
... ...
@@ -371,7 +367,7 @@ static int cli_scanarj(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c
371 371
 		free(metadata.filename);
372 372
 	    continue;
373 373
 	}
374
-	ret = cli_unarj_extract_file(desc, dir, &metadata);
374
+	ret = cli_unarj_extract_file(dir, &metadata);
375 375
 	if (metadata.ofd >= 0) {
376 376
 	    lseek(metadata.ofd, 0, SEEK_SET);
377 377
 	    rc = cli_magic_scandesc(metadata.ofd, ctx);
... ...
@@ -415,11 +411,10 @@ static int cli_scangzip_with_zib_from_the_80s(cli_ctx *ctx, unsigned char *buff)
415 415
     char *tmpname;
416 416
     gzFile gz;
417 417
 
418
-    fd = dup(map->fd);
418
+    fd = dup(fmap_fd(map));
419 419
     if(fd < 0)
420 420
 	return CL_EDUP;
421 421
 
422
-    lseek(fd, 0, SEEK_SET);
423 422
     if(!(gz = gzdopen(fd, "rb"))) {
424 423
 	close(fd);
425 424
 	return CL_EOPEN;
... ...
@@ -562,7 +557,7 @@ static int cli_scangzip(cli_ctx *ctx)
562 562
 
563 563
 
564 564
 #ifndef HAVE_BZLIB_H
565
-static int cli_scanbzip(int desc, cli_ctx *ctx) {
565
+static int cli_scanbzip(cli_ctx *ctx) {
566 566
     cli_warnmsg("cli_scanbzip: bzip2 support not compiled in\n");
567 567
     return CL_CLEAN;
568 568
 }
... ...
@@ -570,108 +565,100 @@ static int cli_scanbzip(int desc, cli_ctx *ctx) {
570 570
 #else
571 571
 
572 572
 #ifdef NOBZ2PREFIX
573
-#define BZ2_bzReadOpen bzReadOpen
574
-#define BZ2_bzReadClose bzReadClose
575
-#define BZ2_bzRead bzRead
573
+#define BZ2_bzDecompressInit bzDecompressInit
574
+#define BZ2_bzDecompress bzDecompress
575
+#define BZ2_bzDecompressEnd bzDecompressEnd
576 576
 #endif
577 577
 
578
-static int cli_scanbzip(int desc, cli_ctx *ctx)
578
+static int cli_scanbzip(cli_ctx *ctx)
579 579
 {
580
-	int fd, bytes, ret = CL_CLEAN, bzerror = 0;
581
-	unsigned long int size = 0;
582
-	char *buff;
583
-	FILE *fs;
584
-	char *tmpname;
585
-	BZFILE *bfd;
586
-
587
-
588
-    if((fs = fdopen(dup(desc), "rb")) == NULL) {
589
-	cli_dbgmsg("Bzip: Can't open descriptor %d.\n", desc);
590
-	return CL_EOPEN;
591
-    }
592
-
593
-    if((bfd = BZ2_bzReadOpen(&bzerror, fs, 0, 0, NULL, 0)) == NULL) {
594
-	cli_dbgmsg("Bzip: Can't initialize bzip2 library (descriptor: %d).\n", desc);
595
-	fclose(fs);
580
+    int ret = CL_CLEAN, fd, rc;
581
+    unsigned long int size = 0;
582
+    char *tmpname;
583
+    bz_stream strm;
584
+    size_t off = 0;
585
+    size_t avail;
586
+    char buf[FILEBUFF];
587
+
588
+    memset(&strm, 0, sizeof(strm));
589
+    strm.next_out = buf;
590
+    strm.avail_out = sizeof(buf);
591
+    rc = BZ2_bzDecompressInit(&strm, 0, 0);
592
+    if (BZ_OK != rc) {
593
+	cli_dbgmsg("Bzip: DecompressInit failed: %d\n", rc);
596 594
 	return CL_EOPEN;
597 595
     }
598 596
 
599 597
     if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
600 598
 	cli_dbgmsg("Bzip: Can't generate temporary file.\n");
601
-	BZ2_bzReadClose(&bzerror, bfd);
602
-	fclose(fs);
599
+	BZ2_bzDecompressEnd(&strm);
603 600
 	return ret;
604 601
     }
605 602
 
606
-    if(!(buff = (char *) cli_malloc(FILEBUFF))) {
607
-	cli_dbgmsg("Bzip: Unable to malloc %u bytes.\n", FILEBUFF);
608
-	close(fd);
609
-	if(!ctx->engine->keeptmp) {
610
-	    if (cli_unlink(tmpname)) {
611
-	    	free(tmpname);
612
-		fclose(fs);
613
-		BZ2_bzReadClose(&bzerror, bfd);
614
-		return CL_EUNLINK;
603
+    do {
604
+	if (!strm.avail_in) {
605
+	    strm.next_in = (void*)fmap_need_off_once_len(*ctx->fmap, off, FILEBUFF, &avail);
606
+	    strm.avail_in = avail;
607
+	    off += avail;
608
+	    if (!strm.avail_in) {
609
+		cli_dbgmsg("Bzip: premature end of compressed stream\n");
610
+		break;
615 611
 	    }
616 612
 	}
617
-	free(tmpname);	
618
-	fclose(fs);
619
-	BZ2_bzReadClose(&bzerror, bfd);
620
-	return CL_EMEM;
621
-    }
622
-
623
-    while((bytes = BZ2_bzRead(&bzerror, bfd, buff, FILEBUFF)) > 0) {
624
-	size += bytes;
625 613
 
626
-	if(cli_checklimits("Bzip", ctx, size + FILEBUFF, 0, 0)!=CL_CLEAN)
614
+	rc = BZ2_bzDecompress(&strm);
615
+	if (BZ_OK != rc && BZ_STREAM_END != rc) {
616
+	    cli_dbgmsg("Bzip: decompress error: %d\n", rc);
627 617
 	    break;
618
+	}
628 619
 
629
-	if(cli_writen(fd, buff, bytes) != bytes) {
630
-	    cli_dbgmsg("Bzip: Can't write to file.\n");
631
-	    BZ2_bzReadClose(&bzerror, bfd);
632
-	    close(fd);
633
-	    if(!ctx->engine->keeptmp) {
634
-		if (cli_unlink(tmpname)) {
635
-		    free(tmpname);
636
-		    free(buff);
637
-		    fclose(fs);
638
-		    return CL_EUNLINK;
620
+	if (!strm.avail_out || BZ_STREAM_END == rc) {
621
+	    size += sizeof(buf) - strm.avail_out;
622
+
623
+	    if(cli_checklimits("Bzip", ctx, size + FILEBUFF, 0, 0)!=CL_CLEAN)
624
+		break;
625
+
626
+	    if(cli_writen(fd, buf, sizeof(buf) - strm.avail_out) != sizeof(buf) - strm.avail_out) {
627
+		cli_dbgmsg("Bzip: Can't write to file.\n");
628
+		BZ2_bzDecompressEnd(&strm);
629
+		close(fd);
630
+		if(!ctx->engine->keeptmp) {
631
+		    if (cli_unlink(tmpname)) {
632
+			free(tmpname);
633
+			return CL_EUNLINK;
634
+		    }
639 635
 		}
636
+		free(tmpname);
637
+		return CL_EWRITE;
640 638
 	    }
641
-	    free(tmpname);	
642
-	    free(buff);
643
-	    fclose(fs);
644
-	    return CL_EWRITE;
639
+	    strm.next_out = buf;
640
+	    strm.avail_out = sizeof(buf);
645 641
 	}
646
-    }
642
+    } while (BZ_STREAM_END != rc);
647 643
 
648
-    free(buff);
649
-    BZ2_bzReadClose(&bzerror, bfd);
644
+    BZ2_bzDecompressEnd(&strm);
650 645
 
651 646
     if(ret == CL_VIRUS) {
652 647
 	close(fd);
653 648
 	if(!ctx->engine->keeptmp)
654 649
 	    if (cli_unlink(tmpname)) ret = CL_EUNLINK;
655
-	free(tmpname);	
656
-	fclose(fs);
650
+	free(tmpname);
657 651
 	return ret;
658 652
     }
659 653
 
660
-    lseek(fd, 0, SEEK_SET);
661 654
     if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
662 655
 	cli_dbgmsg("Bzip: Infected with %s\n", *ctx->virname);
663 656
     }
664 657
     close(fd);
665 658
     if(!ctx->engine->keeptmp)
666 659
 	if (cli_unlink(tmpname)) ret = CL_EUNLINK;
667
-    free(tmpname);	
668
-    fclose(fs);
660
+    free(tmpname);
669 661
 
670 662
     return ret;
671 663
 }
672 664
 #endif
673 665
 
674
-static int cli_scanszdd(int desc, cli_ctx *ctx)
666
+static int cli_scanszdd(cli_ctx *ctx)
675 667
 {
676 668
 	int ofd, ret;
677 669
 	char *tmpname;
... ...
@@ -684,8 +671,7 @@ static int cli_scanszdd(int desc, cli_ctx *ctx)
684 684
 	return ret;
685 685
     }
686 686
 
687
-    lseek(desc, 0, SEEK_SET);
688
-    ret = cli_msexpand(desc, ofd, ctx);
687
+    ret = cli_msexpand(ctx, ofd);
689 688
 
690 689
     if(ret != CL_SUCCESS) { /* CL_VIRUS or some error */
691 690
 	close(ofd);
... ...
@@ -696,7 +682,6 @@ static int cli_scanszdd(int desc, cli_ctx *ctx)
696 696
     }
697 697
 
698 698
     cli_dbgmsg("MSEXPAND: Decompressed into %s\n", tmpname);
699
-    lseek(ofd, 0, SEEK_SET);
700 699
     ret = cli_magic_scandesc(ofd, ctx);
701 700
     close(ofd);
702 701
     if(!ctx->engine->keeptmp)
... ...
@@ -706,7 +691,7 @@ static int cli_scanszdd(int desc, cli_ctx *ctx)
706 706
     return ret;
707 707
 }
708 708
 
709
-static int cli_scanmscab(int desc, cli_ctx *ctx, off_t sfx_offset)
709
+static int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset)
710 710
 {
711 711
 	char *tempname;
712 712
 	int ret;
... ...
@@ -718,7 +703,7 @@ static int cli_scanmscab(int desc, cli_ctx *ctx, off_t sfx_offset)
718 718
 
719 719
     cli_dbgmsg("in cli_scanmscab()\n");
720 720
 
721
-    if((ret = cab_open(desc, sfx_offset, &cab)))
721
+    if((ret = cab_open(*ctx->fmap, sfx_offset, &cab)))
722 722
 	return ret;
723 723
 
724 724
     for(file = cab.files; file; file = file->next) {
... ...
@@ -1045,7 +1030,6 @@ static int cli_scanhtml(cli_ctx *ctx)
1045 1045
 	    if(fd >= 0) {
1046 1046
 		    ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR, NULL);
1047 1047
 		    if (ret == CL_CLEAN) {
1048
-			    lseek(fd, 0, SEEK_SET);
1049 1048
 			    ret = cli_scandesc(fd, ctx, CL_TYPE_TEXT_ASCII, 0, NULL, AC_SCAN_VIR, NULL);
1050 1049
 		    }
1051 1050
 		    close(fd);
... ...
@@ -1270,7 +1254,7 @@ static int cli_scanole2(cli_ctx *ctx)
1270 1270
     return ret;
1271 1271
 }
1272 1272
 
1273
-static int cli_scantar(int desc, cli_ctx *ctx, unsigned int posix)
1273
+static int cli_scantar(cli_ctx *ctx, unsigned int posix)
1274 1274
 {
1275 1275
 	char *dir;
1276 1276
 	int ret = CL_CLEAN;
... ...
@@ -1288,7 +1272,7 @@ static int cli_scantar(int desc, cli_ctx *ctx, unsigned int posix)
1288 1288
 	return CL_ETMPDIR;
1289 1289
     }
1290 1290
 
1291
-    ret = cli_untar(dir, desc, posix, ctx);
1291
+    ret = cli_untar(dir, posix, ctx);
1292 1292
 
1293 1293
     if(!ctx->engine->keeptmp)
1294 1294
 	cli_rmdirs(dir);
... ...
@@ -1331,7 +1315,6 @@ static int cli_scanmschm(cli_ctx *ctx)
1331 1331
 	}
1332 1332
 	ret = cli_chm_extract_file(dir, &metadata, ctx);
1333 1333
 	if (ret == CL_SUCCESS) {
1334
-	    lseek(metadata.ofd, 0, SEEK_SET);
1335 1334
 	    rc = cli_magic_scandesc(metadata.ofd, ctx);
1336 1335
 	    close(metadata.ofd);
1337 1336
 	    if (rc == CL_VIRUS) {
... ...
@@ -1357,7 +1340,7 @@ static int cli_scanmschm(cli_ctx *ctx)
1357 1357
     return ret;
1358 1358
 }
1359 1359
 
1360
-static int cli_scanscrenc(int desc, cli_ctx *ctx)
1360
+static int cli_scanscrenc(cli_ctx *ctx)
1361 1361
 {
1362 1362
 	char *tempname;
1363 1363
 	int ret = CL_CLEAN;
... ...
@@ -1373,7 +1356,7 @@ static int cli_scanscrenc(int desc, cli_ctx *ctx)
1373 1373
 	return CL_ETMPDIR;
1374 1374
     }
1375 1375
 
1376
-    if (html_screnc_decode(desc, tempname))
1376
+    if (html_screnc_decode(*ctx->fmap, tempname))
1377 1377
 	ret = cli_scandir(tempname, ctx);
1378 1378
 
1379 1379
     if(!ctx->engine->keeptmp)
... ...
@@ -1383,11 +1366,11 @@ static int cli_scanscrenc(int desc, cli_ctx *ctx)
1383 1383
     return ret;
1384 1384
 }
1385 1385
 
1386
-static int cli_scanriff(int desc, cli_ctx *ctx)
1386
+static int cli_scanriff(cli_ctx *ctx)
1387 1387
 {
1388 1388
 	int ret = CL_CLEAN;
1389 1389
 
1390
-    if(cli_check_riff_exploit(desc) == 2) {
1390
+    if(cli_check_riff_exploit(ctx) == 2) {
1391 1391
 	ret = CL_VIRUS;
1392 1392
 	*ctx->virname = "Heuristics.Exploit.W32.MS05-002";
1393 1393
     }
... ...
@@ -1395,11 +1378,11 @@ static int cli_scanriff(int desc, cli_ctx *ctx)
1395 1395
     return ret;
1396 1396
 }
1397 1397
 
1398
-static int cli_scanjpeg(int desc, cli_ctx *ctx)
1398
+static int cli_scanjpeg(cli_ctx *ctx)
1399 1399
 {
1400 1400
 	int ret = CL_CLEAN;
1401 1401
 
1402
-    if(cli_check_jpeg_exploit(desc, ctx) == 1) {
1402
+	if(cli_check_jpeg_exploit(ctx, 0) == 1) {
1403 1403
 	ret = CL_VIRUS;
1404 1404
 	*ctx->virname = "Heuristics.Exploit.W32.MS04-028";
1405 1405
     }
... ...
@@ -1407,51 +1390,25 @@ static int cli_scanjpeg(int desc, cli_ctx *ctx)
1407 1407
     return ret;
1408 1408
 }
1409 1409
 
1410
-static int cli_scancryptff(int desc, cli_ctx *ctx)
1410
+static int cli_scancryptff(cli_ctx *ctx)
1411 1411
 {
1412 1412
 	int ret = CL_CLEAN, ndesc;
1413
-	unsigned int length, i;
1414
-	unsigned char *src = NULL, *dest = NULL;
1413
+	unsigned int i;
1414
+	const unsigned char *src;
1415
+	unsigned char *dest = NULL;
1415 1416
 	char *tempfile;
1416
-	struct stat sb;
1417
+	size_t pos;
1418
+	ssize_t bread;
1417 1419
 
1418 1420
 
1419
-    if(fstat(desc, &sb) == -1) {
1420
-	cli_errmsg("CryptFF: Can't fstat descriptor %d\n", desc);
1421
-	return CL_ESTAT;
1422
-    }
1423
-
1424 1421
     /* Skip the CryptFF file header */
1425
-    if(lseek(desc, 0x10, SEEK_SET) < 0) {
1426
-	cli_errmsg("CryptFF: Can't lseek descriptor %d\n", desc);
1427
-	return ret;
1428
-    }
1422
+    pos = 0x10;
1429 1423
 
1430
-    length = sb.st_size  - 0x10;
1431
- 
1432
-    if((dest = (unsigned char *) cli_malloc(length)) == NULL) {
1424
+    if((dest = (unsigned char *) cli_malloc(FILEBUFF)) == NULL) {
1433 1425
 	cli_dbgmsg("CryptFF: Can't allocate memory\n");
1434 1426
         return CL_EMEM;
1435 1427
     }
1436 1428
 
1437
-    if((src = (unsigned char *) cli_malloc(length)) == NULL) {
1438
-	cli_dbgmsg("CryptFF: Can't allocate memory\n");
1439
-	free(dest);
1440
-        return CL_EMEM;
1441
-    }
1442
-
1443
-    if((unsigned int) read(desc, src, length) != length) {
1444
-	cli_dbgmsg("CryptFF: Can't read from descriptor %d\n", desc);
1445
-	free(dest);
1446
-	free(src);
1447
-	return CL_EREAD;
1448
-    }
1449
-
1450
-    for(i = 0; i < length; i++)
1451
-	dest[i] = src[i] ^ (unsigned char) 0xff;
1452
-
1453
-    free(src);
1454
-
1455 1429
     if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) {
1456 1430
 	free(dest);
1457 1431
 	return CL_EMEM;
... ...
@@ -1464,17 +1421,20 @@ static int cli_scancryptff(int desc, cli_ctx *ctx)
1464 1464
 	return CL_ECREAT;
1465 1465
     }
1466 1466
 
1467
-    if(write(ndesc, dest, length) == -1) {
1468
-	cli_dbgmsg("CryptFF: Can't write to descriptor %d\n", ndesc);
1469
-	free(dest);
1470
-	close(ndesc);
1471
-	free(tempfile);
1472
-	return CL_EWRITE;
1467
+    for(; src = fmap_need_off_once_len(*ctx->fmap, pos, FILEBUFF, &bread); pos += bread) {
1468
+	for (i=0;i<bread;i++)
1469
+	    dest[i] = src[i] ^ (unsigned char) 0xff;
1470
+	if(cli_writen(ndesc, dest, bread) == -1) {
1471
+	    cli_dbgmsg("CryptFF: Can't write to descriptor %d\n", ndesc);
1472
+	    free(dest);
1473
+	    close(ndesc);
1474
+	    free(tempfile);
1475
+	    return CL_EWRITE;
1476
+	}
1473 1477
     }
1474 1478
 
1475 1479
     free(dest);
1476 1480
 
1477
-    lseek(ndesc, 0, SEEK_SET);
1478 1481
 
1479 1482
     cli_dbgmsg("CryptFF: Scanning decrypted data\n");
1480 1483
 
... ...
@@ -1515,7 +1475,7 @@ static int cli_scanpdf(cli_ctx *ctx, off_t offset)
1515 1515
     return ret;
1516 1516
 }
1517 1517
 
1518
-static int cli_scantnef(int desc, cli_ctx *ctx)
1518
+static int cli_scantnef(cli_ctx *ctx)
1519 1519
 {
1520 1520
 	int ret;
1521 1521
 	char *dir = cli_gentemp(ctx->engine->tmpdir);
... ...
@@ -1529,7 +1489,7 @@ static int cli_scantnef(int desc, cli_ctx *ctx)
1529 1529
 	return CL_ETMPDIR;
1530 1530
     }
1531 1531
 
1532
-    ret = cli_tnef(dir, desc, ctx);
1532
+    ret = cli_tnef(dir, ctx);
1533 1533
 
1534 1534
     if(ret == CL_CLEAN)
1535 1535
 	ret = cli_scandir(dir, ctx);
... ...
@@ -1567,7 +1527,7 @@ static int cli_scanuuencoded(cli_ctx *ctx)
1567 1567
     return ret;
1568 1568
 }
1569 1569
 
1570
-static int cli_scanmail(int desc, cli_ctx *ctx)
1570
+static int cli_scanmail(cli_ctx *ctx)
1571 1571
 {
1572 1572
 	char *dir;
1573 1573
 	int ret;
... ...
@@ -1588,7 +1548,7 @@ static int cli_scanmail(int desc, cli_ctx *ctx)
1588 1588
     /*
1589 1589
      * Extract the attachments into the temporary directory
1590 1590
      */
1591
-    if((ret = cli_mbox(dir, desc, ctx))) {
1591
+    if((ret = cli_mbox(dir, ctx))) {
1592 1592
 	if(!ctx->engine->keeptmp)
1593 1593
 	    cli_rmdirs(dir);
1594 1594
 	free(dir);
... ...
@@ -1604,13 +1564,15 @@ static int cli_scanmail(int desc, cli_ctx *ctx)
1604 1604
     return ret;
1605 1605
 }
1606 1606
 
1607
-static int cli_scan_structured(int desc, cli_ctx *ctx)
1607
+static int cli_scan_structured(cli_ctx *ctx)
1608 1608
 {
1609 1609
 	char buf[8192];
1610 1610
 	int result = 0;
1611 1611
 	unsigned int cc_count = 0;
1612 1612
 	unsigned int ssn_count = 0;
1613 1613
 	int done = 0;
1614
+	fmap_t *map = *ctx->fmap;
1615
+	size_t pos = 0;
1614 1616
 	int (*ccfunc)(const unsigned char *buffer, int length);
1615 1617
 	int (*ssnfunc)(const unsigned char *buffer, int length);
1616 1618
 
... ...
@@ -1650,7 +1612,8 @@ static int cli_scan_structured(int desc, cli_ctx *ctx)
1650 1650
 	    ssnfunc = NULL;
1651 1651
     }
1652 1652
 
1653
-    while(!done && ((result = cli_readn(desc, buf, 8191)) > 0)) {
1653
+    while(!done && ((result = fmap_readn(map, buf, pos, 8191)) > 0)) {
1654
+	pos += result;
1654 1655
 	if((cc_count += ccfunc((const unsigned char *)buf, result)) >= ctx->engine->min_cc_count)
1655 1656
 	    done = 1;
1656 1657
 
... ...
@@ -1730,7 +1693,6 @@ static int cli_scanembpe(cli_ctx *ctx, off_t offset)
1730 1730
     }
1731 1731
 
1732 1732
     ctx->recursion++;
1733
-    lseek(fd, 0, SEEK_SET);
1734 1733
     corrupted_input = ctx->corrupted_input;
1735 1734
     ctx->corrupted_input = 1;
1736 1735
     ret = cli_magic_scandesc(fd, ctx);
... ...
@@ -1942,7 +1904,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
1942 1942
 			    ctx->container_type = CL_TYPE_RAR;
1943 1943
 			    ctx->container_size = map->len - fpt->offset; /* not precise */
1944 1944
 			    cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
1945
-			    nret = cli_scanrar(map->fd, ctx, fpt->offset, &lastrar);
1945
+			    nret = cli_scanrar(fmap_fd(map), ctx, fpt->offset, &lastrar);
1946 1946
 			}
1947 1947
 			break;
1948 1948
 
... ...
@@ -1960,7 +1922,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
1960 1960
 			    ctx->container_type = CL_TYPE_MSCAB;
1961 1961
 			    ctx->container_size = map->len - fpt->offset; /* not precise */
1962 1962
 			    cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
1963
-			    nret = cli_scanmscab(map->fd, ctx, fpt->offset);
1963
+			    nret = cli_scanmscab(ctx, fpt->offset);
1964 1964
 			}
1965 1965
 			break;
1966 1966
 		    case CL_TYPE_ARJSFX:
... ...
@@ -1968,7 +1930,16 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
1968 1968
 			    ctx->container_type = CL_TYPE_ARJ;
1969 1969
 			    ctx->container_size = map->len - fpt->offset; /* not precise */
1970 1970
 			    cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
1971
-			    nret = cli_scanarj(map->fd, ctx, fpt->offset, &lastrar);
1971
+			    nret = cli_scanarj(ctx, fpt->offset, &lastrar);
1972
+			}
1973
+			break;
1974
+
1975
+		    case CL_TYPE_7ZSFX:
1976
+			if(type != CL_TYPE_7Z && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_7Z)) {
1977
+			    ctx->container_type = CL_TYPE_7Z;
1978
+			    ctx->container_size = map->len - fpt->offset; /* not precise */
1979
+			    cli_dbgmsg("7Zip-SFX signature found at %u\n", (unsigned int) fpt->offset);
1980
+			    nret = cli_7unz(ctx, fpt->offset);
1972 1981
 			}
1973 1982
 			break;
1974 1983
 
... ...
@@ -2067,7 +2038,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
2067 2067
 		ctx->container_size = map->len;
2068 2068
 		if(SCAN_MAIL && type == CL_TYPE_TEXT_ASCII && (DCONF_MAIL & MAIL_CONF_MBOX)) {
2069 2069
 		    *dettype = CL_TYPE_MAIL;
2070
-		    nret = cli_scanmail(map->fd, ctx);
2070
+		    nret = cli_scanmail(ctx);
2071 2071
 		}
2072 2072
 		ctx->container_type = current_container_type;
2073 2073
 		ctx->container_size = current_container_size;
... ...
@@ -2088,7 +2059,7 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
2088 2088
     }
2089 2089
 
2090 2090
     if(ret == CL_VIRUS)
2091
-	cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, map->fd);
2091
+	cli_dbgmsg("%s found\n", *ctx->virname);
2092 2092
 
2093 2093
     return ret;
2094 2094
 }
... ...
@@ -2109,12 +2080,19 @@ static void emax_reached(cli_ctx *ctx) {
2109 2109
 #define LINESTR(x) #x
2110 2110
 #define LINESTR2(x) LINESTR(x)
2111 2111
 #define __AT__  " at line "LINESTR2(__LINE__)
2112
+
2113
+#define early_ret_from_magicscan(retcode) \
2114
+    do {\
2115
+	cli_dbgmsg("cli_magic_scandesc: returning %d %s (no post, no cache)\n", retcode, __AT__);\
2116
+	return retcode;                                                                         \
2117
+    } while(0)
2118
+
2112 2119
 #define ret_from_magicscan(retcode) \
2113 2120
     do {											\
2114 2121
 	cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__); 			\
2115 2122
 	if(ctx->engine->cb_post_scan) {								\
2116 2123
 	    perf_start(ctx, PERFT_POSTCB);							\
2117
-	    switch(ctx->engine->cb_post_scan(desc, retcode, retcode == CL_VIRUS && ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx)) {	\
2124
+	    switch(ctx->engine->cb_post_scan(fmap_fd(*ctx->fmap), retcode, retcode == CL_VIRUS && ctx->virname ? *ctx->virname : NULL, ctx->cb_ctx)) {	\
2118 2125
 	    case CL_BREAK:									\
2119 2126
 		cli_dbgmsg("cli_magic_scandesc: file whitelisted by post_scan callback\n"); 	\
2120 2127
 		perf_stop(ctx, PERFT_POSTCB);							\
... ...
@@ -2132,6 +2110,11 @@ static void emax_reached(cli_ctx *ctx) {
2132 2132
 	    }											\
2133 2133
 	    perf_stop(ctx, PERFT_POSTCB);							\
2134 2134
 	}											\
2135
+	if (retcode == CL_CLEAN && cache_clean) {                                               \
2136
+	    perf_start(ctx, PERFT_CACHE);                                                       \
2137
+	    cache_add(hash, hashed_size, ctx);                                                  \
2138
+	    perf_stop(ctx, PERFT_CACHE);							\
2139
+	}											\
2135 2140
 	return retcode;										\
2136 2141
     } while(0)
2137 2142
 
... ...
@@ -2139,19 +2122,15 @@ static void emax_reached(cli_ctx *ctx) {
2139 2139
 #define CALL_PRESCAN_CB(scanfn)	                                                     \
2140 2140
     if(ctx->engine->scanfn) {				\
2141 2141
 	perf_start(ctx, PERFT_PRECB);                                                        \
2142
-	switch(ctx->engine->scanfn(desc, filetype, ctx->cb_ctx)) {	\
2142
+	switch(ctx->engine->scanfn(fmap_fd(*ctx->fmap), filetype, ctx->cb_ctx)) {	\
2143 2143
 	case CL_BREAK:                                                                       \
2144 2144
 	    cli_dbgmsg("cli_magic_scandesc: file whitelisted by "#scanfn" callback\n");                \
2145
-	    funmap(*ctx->fmap);                                                              \
2146
-	    ctx->fmap--;                                                                     \
2147 2145
 	    perf_stop(ctx, PERFT_PRECB);                                                     \
2148 2146
 	    ret_from_magicscan(CL_CLEAN);                                                    \
2149 2147
 	case CL_VIRUS:                                                                       \
2150 2148
 	    cli_dbgmsg("cli_magic_scandesc: file blacklisted by "#scanfn" callback\n");                \
2151 2149
 	    if(ctx->virname)                                                                 \
2152 2150
 		*ctx->virname = "Detected.By.Callback";                                      \
2153
-	    funmap(*ctx->fmap);                                                              \
2154
-	    ctx->fmap--;                                                                     \
2155 2151
 	    perf_stop(ctx, PERFT_PRECB);                                                     \
2156 2152
 	    ret_from_magicscan(CL_VIRUS);                                                    \
2157 2153
 	case CL_CLEAN:                                                                       \
... ...
@@ -2164,63 +2143,38 @@ static void emax_reached(cli_ctx *ctx) {
2164 2164
 
2165 2165
 
2166 2166
 
2167
-static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2167
+static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
2168 2168
 {
2169 2169
 	int ret = CL_CLEAN;
2170 2170
 	cli_file_t dettype = 0;
2171
-	struct stat sb;
2172 2171
 	uint8_t typercg = 1;
2173 2172
 	cli_file_t current_container_type = ctx->container_type;
2174 2173
 	size_t current_container_size = ctx->container_size, hashed_size;
2175 2174
 	unsigned char hash[16];
2176 2175
 	bitset_t *old_hook_lsig_matches;
2177 2176
 	const char *filetype;
2177
+	int cache_clean = 0;
2178 2178
 
2179
-#ifdef HAVE__INTERNAL__SHA_COLLECT
2180
-    if(ctx->sha_collect>0) ctx->sha_collect = 0;
2181
-#endif
2182
-
2183
-    cli_dbgmsg("in cli_magic_scandesc (reclevel: %u/%u)\n", ctx->recursion, ctx->engine->maxreclevel);
2184 2179
     if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
2185 2180
         cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
2186 2181
 	emax_reached(ctx);
2187
-	ret_from_magicscan(CL_CLEAN);
2188
-    }
2189
-
2190
-    if(fstat(desc, &sb) == -1) {
2191
-	cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc);
2192
-	ret_from_magicscan(CL_ESTAT);
2193
-    }
2194
-
2195
-    if(sb.st_size <= 5) {
2196
-	cli_dbgmsg("Small data (%u bytes)\n", (unsigned int) sb.st_size);
2197
-	ret_from_magicscan(CL_CLEAN);
2182
+	early_ret_from_magicscan(CL_CLEAN);
2198 2183
     }
2199 2184
 
2200 2185
     if(!ctx->engine) {
2201 2186
 	cli_errmsg("CRITICAL: engine == NULL\n");
2202
-	ret_from_magicscan(CL_ENULLARG);
2187
+	early_ret_from_magicscan(CL_ENULLARG);
2203 2188
     }
2204 2189
 
2205 2190
     if(!(ctx->engine->dboptions & CL_DB_COMPILED)) {
2206 2191
 	cli_errmsg("CRITICAL: engine not compiled\n");
2207
-	ret_from_magicscan(CL_EMALFDB);
2192
+	early_ret_from_magicscan(CL_EMALFDB);
2208 2193
     }
2209 2194
 
2210
-    if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN) {
2195
+    if(cli_updatelimits(ctx, (*ctx->fmap)->len)!=CL_CLEAN) {
2211 2196
 	emax_reached(ctx);
2212
-        ret_from_magicscan(CL_CLEAN);
2213
-    }
2214
-
2215
-    ctx->fmap++;
2216
-    perf_start(ctx, PERFT_MAP);
2217
-    if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
2218
-	cli_errmsg("CRITICAL: fmap() failed\n");
2219
-	ctx->fmap--;
2220
-	perf_stop(ctx, PERFT_MAP);
2221
-	ret_from_magicscan(CL_EMEM);
2197
+        early_ret_from_magicscan(CL_CLEAN);
2222 2198
     }
2223
-    perf_stop(ctx, PERFT_MAP);
2224 2199
 
2225 2200
     perf_start(ctx, PERFT_FT);
2226 2201
     if(type == CL_TYPE_ANY)
... ...
@@ -2228,19 +2182,15 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2228 2228
     perf_stop(ctx, PERFT_FT);
2229 2229
     if(type == CL_TYPE_ERROR) {
2230 2230
 	cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
2231
-	funmap(*ctx->fmap);
2232
-	ctx->fmap--;
2233
-	ret_from_magicscan(CL_EREAD);
2231
+	early_ret_from_magicscan(CL_EREAD);
2234 2232
     }
2235 2233
     filetype = cli_ftname(type);
2236 2234
     CALL_PRESCAN_CB(cb_pre_cache);
2237 2235
 
2238 2236
     perf_start(ctx, PERFT_CACHE);
2239 2237
     if(cache_check(hash, ctx) == CL_CLEAN) {
2240
-	funmap(*ctx->fmap);
2241
-	ctx->fmap--;
2242 2238
 	perf_stop(ctx, PERFT_CACHE);
2243
-	ret_from_magicscan(CL_CLEAN);
2239
+	early_ret_from_magicscan(CL_CLEAN);
2244 2240
     }
2245 2241
     perf_stop(ctx, PERFT_CACHE);
2246 2242
     hashed_size = (*ctx->fmap)->len;
... ...
@@ -2254,63 +2204,91 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2254 2254
 	    cli_dbgmsg("Raw mode: No support for special files\n");
2255 2255
 
2256 2256
 	CALL_PRESCAN_CB(cb_pre_scan);
2257
+	/* ret_from_magicscan can be used below here*/
2257 2258
 	if((ret = cli_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR, NULL, hash)) == CL_VIRUS)
2258
-	    cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
2259
+	    cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, fmap_fd(*ctx->fmap));
2259 2260
 	else if(ret == CL_CLEAN) {
2260 2261
 	    if(ctx->recursion != ctx->engine->maxreclevel)
2261
-		cache_add(hash, hashed_size, ctx); /* Only cache if limits are not reached */
2262
-	    else 
2262
+		cache_clean = 1; /* Only cache if limits are not reached */
2263
+	    else
2263 2264
 		emax_reached(ctx);
2264 2265
 	}
2265 2266
 
2266 2267
 	ctx->hook_lsig_matches = old_hook_lsig_matches;
2267
-	funmap(*ctx->fmap);
2268
-	ctx->fmap--;
2269 2268
 	ret_from_magicscan(ret);
2270 2269
     }
2271 2270
 
2272 2271
     CALL_PRESCAN_CB(cb_pre_scan);
2272
+    /* ret_from_magicscan can be used below here*/
2273 2273
 
2274 2274
 #ifdef HAVE__INTERNAL__SHA_COLLECT
2275 2275
     if(!ctx->sha_collect && type==CL_TYPE_MSEXE) ctx->sha_collect = 1;
2276 2276
 #endif
2277
-    lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
2278 2277
 
2279 2278
     ctx->hook_lsig_matches = cli_bitset_init();
2280 2279
     if (!ctx->hook_lsig_matches) {
2281 2280
 	ctx->hook_lsig_matches = old_hook_lsig_matches;
2282
-	ctx->fmap--;
2283 2281
 	ret_from_magicscan(CL_EMEM);
2284 2282
     }
2285 2283
 
2286 2284
     if(type != CL_TYPE_IGNORED && ctx->engine->sdb) {
2287 2285
 	if((ret = cli_scanraw(ctx, type, 0, &dettype, hash)) == CL_VIRUS) {
2288 2286
 	    ret = cli_checkfp(hash, hashed_size, ctx);
2289
-	    funmap(*ctx->fmap);
2290
-	    ctx->fmap--;
2291 2287
 	    cli_bitset_free(ctx->hook_lsig_matches);
2292 2288
 	    ctx->hook_lsig_matches = old_hook_lsig_matches;
2293 2289
 	    ret_from_magicscan(ret);
2294 2290
 	}
2295
-	lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
2296 2291
     }
2297 2292
 
2298 2293
     ctx->recursion++;
2299 2294
     perf_nested_start(ctx, PERFT_CONTAINER, PERFT_SCAN);
2295
+    ctx->container_size = (*ctx->fmap)->len;
2300 2296
     switch(type) {
2301 2297
 	case CL_TYPE_IGNORED:
2302 2298
 	    break;
2303 2299
 
2304 2300
 	case CL_TYPE_RAR:
2305 2301
 	    ctx->container_type = CL_TYPE_RAR;
2306
-	    ctx->container_size = sb.st_size;
2307
-	    if(have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR))
2302
+	    if(have_rar && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_RAR)) {
2303
+		char *tmpname = NULL;
2304
+		int desc = fmap_fd(*ctx->fmap);
2305
+		if (desc == -1) {
2306
+		    size_t pos = 0, len;
2307
+
2308
+		    cli_dbgmsg("fmap not backed by file, dumping ...\n");
2309
+		    if ((ret = cli_gentempfd(((cli_ctx*)ctx)->engine->tmpdir, &tmpname, &desc)) != CL_SUCCESS) {
2310
+			cli_dbgmsg("fmap_fd: failed to generate temporary file.\n");
2311
+			break;
2312
+		    }
2313
+		    do {
2314
+			char *b;
2315
+
2316
+			len = 0;
2317
+			b = fmap_need_off_once_len(*ctx->fmap, pos, BUFSIZ, &len);
2318
+			pos += len;
2319
+			if (b && len > 0) {
2320
+			    if (cli_writen(desc, b, len) != len) {
2321
+				close(desc);
2322
+				unlink(tmpname);
2323
+				cli_warnmsg("fmap_fd_dump: write failed\n");
2324
+				ret = CL_EWRITE;
2325
+				break;
2326
+			    }
2327
+			}
2328
+		    } while (len > 0);
2329
+		    lseek(desc, 0, SEEK_SET);
2330
+		}
2308 2331
 		ret = cli_scanrar(desc, ctx, 0, NULL);
2332
+		if (tmpname) {
2333
+		    close(desc);
2334
+		    unlink(tmpname);
2335
+		    free(tmpname);
2336
+		}
2337
+	    }
2309 2338
 	    break;
2310 2339
 
2311 2340
 	case CL_TYPE_ZIP:
2312 2341
 	    ctx->container_type = CL_TYPE_ZIP;
2313
-	    ctx->container_size = sb.st_size;
2314 2342
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
2315 2343
 		ret = cli_unzip(ctx);
2316 2344
 	    break;
... ...
@@ -2322,40 +2300,36 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2322 2322
 
2323 2323
 	case CL_TYPE_BZ:
2324 2324
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BZ))
2325
-		ret = cli_scanbzip(desc, ctx);
2325
+		ret = cli_scanbzip(ctx);
2326 2326
 	    break;
2327 2327
 
2328 2328
 	case CL_TYPE_ARJ:
2329 2329
 	    ctx->container_type = CL_TYPE_ARJ;
2330
-	    ctx->container_size = sb.st_size;
2331 2330
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ARJ))
2332
-		ret = cli_scanarj(desc, ctx, 0, NULL);
2331
+		ret = cli_scanarj(ctx, 0, NULL);
2333 2332
 	    break;
2334 2333
 
2335 2334
         case CL_TYPE_NULSFT:
2336 2335
 	    ctx->container_type = CL_TYPE_NULSFT;
2337
-	    ctx->container_size = sb.st_size;
2338 2336
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_NSIS))
2339 2337
 		ret = cli_scannulsft(ctx, 0);
2340 2338
 	    break;
2341 2339
 
2342 2340
         case CL_TYPE_AUTOIT:
2343 2341
 	    ctx->container_type = CL_TYPE_AUTOIT;
2344
-	    ctx->container_size = sb.st_size;
2345 2342
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_AUTOIT))
2346 2343
 		ret = cli_scanautoit(ctx, 23);
2347 2344
 	    break;
2348 2345
 
2349 2346
 	case CL_TYPE_MSSZDD:
2350 2347
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_SZDD))
2351
-		ret = cli_scanszdd(desc, ctx);
2348
+		ret = cli_scanszdd(ctx);
2352 2349
 	    break;
2353 2350
 
2354 2351
 	case CL_TYPE_MSCAB:
2355 2352
 	    ctx->container_type = CL_TYPE_MSCAB;
2356
-	    ctx->container_size = sb.st_size;
2357 2353
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CAB))
2358
-		ret = cli_scanmscab(desc, ctx, 0);
2354
+		ret = cli_scanmscab(ctx, 0);
2359 2355
 	    break;
2360 2356
 
2361 2357
 	case CL_TYPE_HTML:
... ...
@@ -2382,21 +2356,19 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2382 2382
 
2383 2383
 	case CL_TYPE_RTF:
2384 2384
 	    ctx->container_type = CL_TYPE_RTF;
2385
-	    ctx->container_size = sb.st_size;
2386 2385
 	    if(SCAN_ARCHIVE && (DCONF_DOC & DOC_CONF_RTF))
2387
-		ret = cli_scanrtf(desc, ctx);
2386
+		ret = cli_scanrtf(ctx);
2388 2387
 	    break;
2389 2388
 
2390 2389
 	case CL_TYPE_MAIL:
2391 2390
 	    ctx->container_type = CL_TYPE_MAIL;
2392
-	    ctx->container_size = sb.st_size;
2393 2391
 	    if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX))
2394
-		ret = cli_scanmail(desc, ctx);
2392
+		ret = cli_scanmail(ctx);
2395 2393
 	    break;
2396 2394
 
2397 2395
 	case CL_TYPE_TNEF:
2398 2396
 	    if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_TNEF))
2399
-		ret = cli_scantnef(desc, ctx);
2397
+		ret = cli_scantnef(ctx);
2400 2398
 	    break;
2401 2399
 
2402 2400
 	case CL_TYPE_UUENCODED:
... ...
@@ -2406,65 +2378,56 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2406 2406
 
2407 2407
 	case CL_TYPE_MSCHM:
2408 2408
 	    ctx->container_type = CL_TYPE_MSCHM;
2409
-	    ctx->container_size = sb.st_size;
2410 2409
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CHM))
2411 2410
 		ret = cli_scanmschm(ctx);
2412 2411
 	    break;
2413 2412
 
2414 2413
 	case CL_TYPE_MSOLE2:
2415 2414
 	    ctx->container_type = CL_TYPE_MSOLE2;
2416
-	    ctx->container_size = sb.st_size;
2417 2415
 	    if(SCAN_OLE2 && (DCONF_ARCH & ARCH_CONF_OLE2))
2418 2416
 		ret = cli_scanole2(ctx);
2419 2417
 	    break;
2420 2418
 
2421 2419
 	case CL_TYPE_7Z:
2422 2420
 	    ctx->container_type = CL_TYPE_7Z;
2423
-	    ctx->container_size = sb.st_size;
2424 2421
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_7Z))
2425
-		ret = cli_7unz(desc, ctx);
2422
+		ret = cli_7unz(ctx, 0);
2426 2423
 	    break;
2427 2424
 
2428 2425
 	case CL_TYPE_POSIX_TAR:
2429 2426
 	    ctx->container_type = CL_TYPE_POSIX_TAR;
2430
-	    ctx->container_size = sb.st_size;
2431 2427
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
2432
-		ret = cli_scantar(desc, ctx, 1);
2428
+		ret = cli_scantar(ctx, 1);
2433 2429
 	    break;
2434 2430
 
2435 2431
 	case CL_TYPE_OLD_TAR:
2436 2432
 	    ctx->container_type = CL_TYPE_OLD_TAR;
2437
-	    ctx->container_size = sb.st_size;
2438 2433
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_TAR))
2439
-		ret = cli_scantar(desc, ctx, 0);
2434
+		ret = cli_scantar(ctx, 0);
2440 2435
 	    break;
2441 2436
 
2442 2437
 	case CL_TYPE_CPIO_OLD:
2443 2438
 	    ctx->container_type = CL_TYPE_CPIO_OLD;
2444
-	    ctx->container_size = sb.st_size;
2445 2439
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
2446
-		ret = cli_scancpio_old(desc, ctx);
2440
+		ret = cli_scancpio_old(ctx);
2447 2441
 	    break;
2448 2442
 
2449 2443
 	case CL_TYPE_CPIO_ODC:
2450 2444
 	    ctx->container_type = CL_TYPE_CPIO_ODC;
2451
-	    ctx->container_size = sb.st_size;
2452 2445
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
2453
-		ret = cli_scancpio_odc(desc, ctx);
2446
+		ret = cli_scancpio_odc(ctx);
2454 2447
 	    break;
2455 2448
 
2456 2449
 	case CL_TYPE_CPIO_NEWC:
2457 2450
 	    ctx->container_type = CL_TYPE_CPIO_NEWC;
2458
-	    ctx->container_size = sb.st_size;
2459 2451
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
2460
-		ret = cli_scancpio_newc(desc, ctx, 0);
2452
+		ret = cli_scancpio_newc(ctx, 0);
2461 2453
 	    break;
2462 2454
 
2463 2455
 	case CL_TYPE_CPIO_CRC:
2464 2456
 	    ctx->container_type = CL_TYPE_CPIO_CRC;
2465
-	    ctx->container_size = sb.st_size;
2466 2457
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_CPIO))
2467
-		ret = cli_scancpio_newc(desc, ctx, 1);
2458
+		ret = cli_scancpio_newc(ctx, 1);
2468 2459
 	    break;
2469 2460
 
2470 2461
 	case CL_TYPE_BINHEX:
... ...
@@ -2474,17 +2437,17 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2474 2474
 
2475 2475
 	case CL_TYPE_SCRENC:
2476 2476
 	    if(DCONF_OTHER & OTHER_CONF_SCRENC)
2477
-		ret = cli_scanscrenc(desc, ctx);
2477
+		ret = cli_scanscrenc(ctx);
2478 2478
 	    break;
2479 2479
 
2480 2480
 	case CL_TYPE_RIFF:
2481 2481
 	    if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_RIFF))
2482
-		ret = cli_scanriff(desc, ctx);
2482
+		ret = cli_scanriff(ctx);
2483 2483
 	    break;
2484 2484
 
2485 2485
 	case CL_TYPE_GRAPHICS:
2486 2486
 	    if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_JPEG))
2487
-		ret = cli_scanjpeg(desc, ctx);
2487
+		ret = cli_scanjpeg(ctx);
2488 2488
 
2489 2489
 	    if(ctx->img_validate && SCAN_ALGO && ret != CL_VIRUS)
2490 2490
 		ret = cli_parsejpeg(ctx);
... ...
@@ -2498,14 +2461,13 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2498 2498
 
2499 2499
         case CL_TYPE_PDF: /* FIXMELIMITS: pdf should be an archive! */
2500 2500
 	    ctx->container_type = CL_TYPE_PDF;
2501
-	    ctx->container_size = sb.st_size;
2502 2501
 	    if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF))
2503 2502
 		ret = cli_scanpdf(ctx, 0);
2504 2503
 	    break;
2505 2504
 
2506 2505
 	case CL_TYPE_CRYPTFF:
2507 2506
 	    if(DCONF_OTHER & OTHER_CONF_CRYPTFF)
2508
-		ret = cli_scancryptff(desc, ctx);
2507
+		ret = cli_scancryptff(ctx);
2509 2508
 	    break;
2510 2509
 
2511 2510
 	case CL_TYPE_ELF:
... ...
@@ -2525,14 +2487,14 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2525 2525
 
2526 2526
 	case CL_TYPE_SIS:
2527 2527
 	    ctx->container_type = CL_TYPE_SIS;
2528
-	    ctx->container_size = sb.st_size;
2529 2528
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_SIS))
2530
-		ret = cli_scansis(desc, ctx);
2529
+		ret = cli_scansis(ctx);
2531 2530
 	    break;
2532 2531
 
2533 2532
 	case CL_TYPE_BINARY_DATA:
2533
+	case CL_TYPE_TEXT_UTF16BE:
2534 2534
 	    if(SCAN_ALGO && (DCONF_OTHER & OTHER_CONF_MYDOOMLOG))
2535
-		ret = cli_check_mydoom_log(desc, ctx);
2535
+		ret = cli_check_mydoom_log(ctx);
2536 2536
 	    break;
2537 2537
 
2538 2538
 	case CL_TYPE_TEXT_ASCII:
... ...
@@ -2540,7 +2502,7 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2540 2540
 		/* TODO: consider calling this from cli_scanscript() for
2541 2541
 		 * a normalised text
2542 2542
 		 */
2543
-		ret = cli_scan_structured(desc, ctx);
2543
+		ret = cli_scan_structured(ctx);
2544 2544
 	    break;
2545 2545
 
2546 2546
 	default:
... ...
@@ -2553,15 +2515,13 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2553 2553
 
2554 2554
     if(ret == CL_VIRUS) {
2555 2555
 	ret = cli_checkfp(hash, hashed_size, ctx);
2556
-	funmap(*ctx->fmap);
2557
-	ctx->fmap--;
2558 2556
 	cli_bitset_free(ctx->hook_lsig_matches);
2559 2557
 	ctx->hook_lsig_matches = old_hook_lsig_matches;
2560 2558
 	ret_from_magicscan(ret);
2561 2559
     }
2562 2560
 
2563 2561
     if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
2564
-	if(sb.st_size > 1048576) {
2562
+	if((*ctx->fmap)->len > 1048576) {
2565 2563
 	    cli_dbgmsg("cli_magic_scandesc: Not checking for embedded PEs (zip file > 1 MB)\n");
2566 2564
 	    typercg = 0;
2567 2565
 	}
... ...
@@ -2571,8 +2531,6 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2571 2571
     if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && !ctx->engine->sdb) {
2572 2572
 	if(cli_scanraw(ctx, type, typercg, &dettype, hash) == CL_VIRUS) {
2573 2573
 	    ret =  cli_checkfp(hash, hashed_size, ctx);
2574
-	    funmap(*ctx->fmap);
2575
-	    ctx->fmap--;
2576 2574
 	    cli_bitset_free(ctx->hook_lsig_matches);
2577 2575
 	    ctx->hook_lsig_matches = old_hook_lsig_matches;
2578 2576
 	    ret_from_magicscan(ret);
... ...
@@ -2580,7 +2538,6 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2580 2580
     }
2581 2581
 
2582 2582
     ctx->recursion++;
2583
-    lseek(desc, 0, SEEK_SET);
2584 2583
     switch(type) {
2585 2584
 	/* bytecode hooks triggered by a lsig must be a hook
2586 2585
 	 * called from one of the functions here */
... ...
@@ -2592,8 +2549,7 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2592 2592
 	    if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
2593 2593
 	        ret = cli_scanscript(ctx);
2594 2594
 	    if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX) && ret != CL_VIRUS && (ctx->container_type == CL_TYPE_MAIL || dettype == CL_TYPE_MAIL)) {
2595
-		lseek(desc, 0, SEEK_SET);
2596
-		ret = cli_scandesc(desc, ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR, NULL);
2595
+		ret = cli_fmap_scandesc(ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR, NULL, NULL);
2597 2596
 	    }
2598 2597
 	    perf_nested_stop(ctx, PERFT_SCRIPT, PERFT_SCAN);
2599 2598
 	    break;
... ...
@@ -2616,8 +2572,6 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2616 2616
     if(ret == CL_VIRUS)
2617 2617
 	ret = cli_checkfp(hash, hashed_size, ctx);
2618 2618
     ctx->recursion--;
2619
-    funmap(*ctx->fmap);
2620
-    ctx->fmap--;
2621 2619
     cli_bitset_free(ctx->hook_lsig_matches);
2622 2620
     ctx->hook_lsig_matches = old_hook_lsig_matches;
2623 2621
 
... ...
@@ -2626,11 +2580,9 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2626 2626
 	case CL_EMAXREC:
2627 2627
 	case CL_EMAXSIZE:
2628 2628
 	case CL_EMAXFILES:
2629
-	    cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(ret));
2629
+	    cli_dbgmsg("Descriptor[%d]: %s\n", fmap_fd(*ctx->fmap), cl_strerror(ret));
2630 2630
 	case CL_CLEAN:
2631
-	    perf_start(ctx, PERFT_CACHE);
2632
-	    cache_add(hash, hashed_size, ctx);
2633
-	    perf_stop(ctx, PERFT_CACHE);
2631
+	    cache_clean = 1;
2634 2632
 	    ret_from_magicscan(CL_CLEAN);
2635 2633
 	default:
2636 2634
 	    ret_from_magicscan(ret);
... ...
@@ -2639,12 +2591,42 @@ static int magic_scandesc(int desc, cli_ctx *ctx, cli_file_t type)
2639 2639
 
2640 2640
 int cli_magic_scandesc(int desc, cli_ctx *ctx)
2641 2641
 {
2642
-    return magic_scandesc(desc, ctx, CL_TYPE_ANY);
2642
+    struct stat sb;
2643
+    int ret;
2644
+
2645
+#ifdef HAVE__INTERNAL__SHA_COLLECT
2646
+    if(ctx->sha_collect>0) ctx->sha_collect = 0;
2647
+#endif
2648
+    cli_dbgmsg("in cli_magic_scandesc (reclevel: %u/%u)\n", ctx->recursion, ctx->engine->maxreclevel);
2649
+    if(fstat(desc, &sb) == -1) {
2650
+	cli_errmsg("magic_scandesc: Can't fstat descriptor %d\n", desc);
2651
+	early_ret_from_magicscan(CL_ESTAT);
2652
+    }
2653
+    if(sb.st_size <= 5) {
2654
+	cli_dbgmsg("Small data (%u bytes)\n", (unsigned int) sb.st_size);
2655
+	early_ret_from_magicscan(CL_CLEAN);
2656
+    }
2657
+
2658
+    ctx->fmap++;
2659
+    perf_start(ctx, PERFT_MAP);
2660
+    if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
2661
+	cli_errmsg("CRITICAL: fmap() failed\n");
2662
+	ctx->fmap--;
2663
+	perf_stop(ctx, PERFT_MAP);
2664
+	early_ret_from_magicscan(CL_EMEM);
2665
+    }
2666
+    perf_stop(ctx, PERFT_MAP);
2667
+
2668
+    ret = magic_scandesc(ctx, CL_TYPE_ANY);
2669
+
2670
+    funmap(*ctx->fmap);
2671
+    ctx->fmap--;
2672
+    return ret;
2643 2673
 }
2644 2674
 
2645
-int cli_magic_scandesc_type(int desc, cli_ctx *ctx, cli_file_t type)
2675
+int cli_magic_scandesc_type(cli_ctx *ctx, cli_file_t type)
2646 2676
 {
2647
-    return magic_scandesc(desc, ctx, type);
2677
+    return magic_scandesc(ctx, type);
2648 2678
 }
2649 2679
 
2650 2680
 int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions)
... ...
@@ -2652,7 +2634,64 @@ int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, cons
2652 2652
     return cl_scandesc_callback(desc, virname, scanned, engine, scanoptions, NULL);
2653 2653
 }
2654 2654
 
2655
-int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context)
2655
+/* length = 0, till the end */
2656
+int cli_map_scandesc(cl_fmap_t *map, off_t offset, size_t length, cli_ctx *ctx)
2657
+{
2658
+    off_t old_off = map->nested_offset;
2659
+    size_t old_len = map->len;
2660
+    int ret;
2661
+
2662
+    cli_dbgmsg("cli_map_scandesc: [%ld, +%ld), [%ld, +%ld)\n",
2663
+	       old_off, old_len, offset, length);
2664
+    if (offset < 0 || offset >= length) {
2665
+	cli_dbgmsg("Invalid offset: %ld\n", (long)offset);
2666
+	return CL_CLEAN;
2667
+    }
2668
+
2669
+    if (!length) length = old_len - offset;
2670
+    if (length > old_len - offset) {
2671
+	cli_dbgmsg("Data truncated: %ld -> %ld\n",
2672
+		   length, old_len - offset);
2673
+	length = old_len - offset;
2674
+    }
2675
+
2676
+    if (length <= 5) {
2677
+	cli_dbgmsg("Small data (%u bytes)\n", (unsigned int) length);
2678
+	return CL_CLEAN;
2679
+    }
2680
+    ctx->fmap++;
2681
+    *ctx->fmap = map;
2682
+    /* can't change offset because then we'd have to discard/move cached
2683
+     * data, instead use another offset to reuse the already cached data */
2684
+    map->nested_offset += offset;
2685
+    map->len = length;
2686
+    map->real_len = map->nested_offset + length;
2687
+    if (CLI_ISCONTAINED(old_off, old_len, map->nested_offset, map->len)) {
2688
+	ret = magic_scandesc(ctx, CL_TYPE_ANY);
2689
+    } else {
2690
+	cli_warnmsg("internal map error: %ld, %ld; %ld, %ld\n", old_off, old_off + old_len,
2691
+		    map->offset,map->nested_offset+map->len);
2692
+    }
2693
+
2694
+    ctx->fmap--;
2695
+    map->nested_offset = old_off;
2696
+    map->len = old_len;
2697
+    return ret;
2698
+}
2699
+
2700
+int cli_mem_scandesc(const void *buffer, size_t length, cli_ctx *ctx)
2701
+{
2702
+    int ret;
2703
+    fmap_t *map = cl_fmap_open_memory(buffer, length);
2704
+    if (!map) {
2705
+	return CL_EMAP;
2706
+    }
2707
+    ret = cli_map_scandesc(map, 0, length, ctx);
2708
+    cl_fmap_close(map);
2709
+    return ret;
2710
+}
2711
+
2712
+static int scan_common(int desc, cl_fmap_t *map, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context)
2656 2713
 {
2657 2714
     cli_ctx ctx;
2658 2715
     int rc;
... ...
@@ -2692,7 +2731,7 @@ int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scan
2692 2692
 #endif
2693 2693
 
2694 2694
     cli_logg_setup(&ctx);
2695
-    rc = cli_magic_scandesc(desc, &ctx);
2695
+    rc = map ? cli_map_scandesc(map, 0, map->len, &ctx) : cli_magic_scandesc(desc, &ctx);
2696 2696
 
2697 2697
     cli_bitset_free(ctx.hook_lsig_matches);
2698 2698
     free(ctx.fmap);
... ...
@@ -2703,6 +2742,16 @@ int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scan
2703 2703
     return rc;
2704 2704
 }
2705 2705
 
2706
+int cl_scandesc_callback(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context)
2707
+{
2708
+    return scan_common(desc, NULL, virname, scanned, engine, scanoptions, context);
2709
+}
2710
+
2711
+int cl_scanmap_callback(cl_fmap_t *map, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, unsigned int scanoptions, void *context)
2712
+{
2713
+    return scan_common(-1, map, virname, scanned, engine, scanoptions, context);
2714
+}
2715
+
2706 2716
 int cli_found_possibly_unwanted(cli_ctx* ctx)
2707 2717
 {
2708 2718
 	if(ctx->virname) {
... ...
@@ -26,7 +26,9 @@
26 26
 #include "filetypes.h"
27 27
 
28 28
 int cli_magic_scandesc(int desc, cli_ctx *ctx);
29
-int cli_magic_scandesc_type(int desc, cli_ctx *ctx, cli_file_t type);
29
+int cli_magic_scandesc_type(cli_ctx *ctx, cli_file_t type);
30
+int cli_map_scandesc(cl_fmap_t *map, off_t offset, size_t length, cli_ctx *ctx);
31
+int cli_mem_scandesc(const void *buffer, size_t length, cli_ctx *ctx);
30 32
 int cli_found_possibly_unwanted(cli_ctx* ctx);
31 33
 
32 34
 #endif
... ...
@@ -43,22 +43,22 @@
43 43
 #include "scanners.h"
44 44
 #include "sis.h"
45 45
 
46
-#define EC32(x) le32_to_host(x)
47
-#define EC16(x) le16_to_host(x)
46
+#define EC32(x) cli_readint32(&(x))
47
+#define EC16(x) cli_readint16(&(x))
48 48
 
49
-static int real_scansis(FILE *, cli_ctx *, const char *);
50
-static int real_scansis9x(FILE *, cli_ctx *, const char *);
49
+static int real_scansis(cli_ctx *, const char *);
50
+static int real_scansis9x(cli_ctx *, const char *);
51 51
 
52 52
 /*************************************************
53 53
        This is the wrapper to the old and new
54 54
             format handlers - see below.
55 55
  *************************************************/
56 56
 
57
-int cli_scansis(int desc, cli_ctx *ctx) {
58
-  FILE *f;
59
-  int i;
57
+int cli_scansis(cli_ctx *ctx) {
60 58
   char *tmpd;
59
+  unsigned int i;
61 60
   uint32_t uid[4];
61
+  fmap_t *map = *ctx->fmap;
62 62
 
63 63
   cli_dbgmsg("in scansis()\n");
64 64
 
... ...
@@ -72,40 +72,24 @@ int cli_scansis(int desc, cli_ctx *ctx) {
72 72
   if (ctx->engine->keeptmp)
73 73
     cli_dbgmsg("SIS: Extracting files to %s\n", tmpd);
74 74
 
75
-  if ((i=dup(desc))==-1) {
76
-    cli_dbgmsg("SIS: dup() failed\n");
77
-    cli_rmdirs(tmpd);
78
-    free(tmpd);
79
-    return CL_EDUP;
80
-  }
81
-  if (!(f=fdopen(i, "rb"))) {
82
-    cli_dbgmsg("SIS: fdopen() failed\n");
83
-    close(i);
84
-    cli_rmdirs(tmpd);
85
-    free(tmpd);
86
-    return CL_EOPEN;
87
-  }
88
-  rewind(f);
89
-  if (fread(uid, 16, 1, f)!=1) {
75
+  if (fmap_readn(map, &uid, 0, 16) != 16) {
90 76
     cli_dbgmsg("SIS: unable to read UIDs\n");
91 77
     cli_rmdirs(tmpd);
92 78
     free(tmpd);
93
-    fclose(f);
94 79
     return CL_EREAD;
95 80
   }
96 81
 
97 82
   cli_dbgmsg("SIS: UIDS %x %x %x - %x\n", EC32(uid[0]), EC32(uid[1]), EC32(uid[2]), EC32(uid[3]));
98
-  if (uid[2]==EC32(0x10000419))
99
-    i=real_scansis(f, ctx, tmpd);
100
-  else if(uid[0]==EC32(0x10201a7a)) {
101
-    i=real_scansis9x(f, ctx, tmpd);
83
+  if (uid[2]==le32_to_host(0x10000419))
84
+    i=real_scansis(ctx, tmpd);
85
+  else if(uid[0]==le32_to_host(0x10201a7a)) {
86
+    i=real_scansis9x(ctx, tmpd);
102 87
   }
103 88
 
104 89
   if (!ctx->engine->keeptmp)
105 90
     cli_rmdirs(tmpd);
106 91
 
107 92
   free(tmpd);
108
-  fclose(f);
109 93
   return i;
110 94
 }
111 95
 
... ...
@@ -141,11 +125,12 @@ enum {
141 141
 #define GETD(VAR) \
142 142
   if (sleft<4) { \
143 143
     memcpy(buff, buff+smax-sleft, sleft); \
144
-    if ((smax=fread(buff+sleft,1,BUFSIZ-sleft,f)+sleft)<4) { \
144
+    if ((smax=fmap_readn(map, buff+sleft, pos, BUFSIZ-sleft)+sleft)<4) { \
145 145
       cli_dbgmsg("SIS: EOF\n"); \
146 146
       free(alangs); \
147 147
       return CL_CLEAN; \
148 148
     } \
149
+    pos += smax - sleft;\
149 150
     sleft=smax; \
150 151
   } \
151 152
   VAR = cli_readint32(&buff[smax-sleft]); \
... ...
@@ -155,12 +140,13 @@ enum {
155 155
 #define GETD2(VAR) {\
156 156
   if (sleft<4) { \
157 157
     memcpy(buff, buff+smax-sleft, sleft); \
158
-    if ((smax=fread(buff+sleft,1,BUFSIZ-sleft,f)+sleft)<4) { \
158
+    if ((smax=fmap_readn(map, buff+sleft, pos, BUFSIZ-sleft)+sleft)<4) { \
159 159
       cli_dbgmsg("SIS: EOF\n"); \
160 160
       free(alangs); \
161 161
       free(ptrs); \
162 162
       return CL_CLEAN; \
163 163
     } \
164
+    pos += smax - sleft;\
164 165
     sleft=smax; \
165 166
   } \
166 167
   VAR = cli_readint32(&buff[smax-sleft]); \
... ...
@@ -175,14 +161,15 @@ enum {
175 175
       free(alangs); \
176 176
       return CL_CLEAN; \
177 177
     } \
178
-    fseek(f, (N)-sleft, SEEK_CUR); \
179
-    sleft=smax=fread(buff,1,BUFSIZ,f); \
178
+    pos += (N)-sleft;\
179
+    sleft=smax=fmap_readn(map, buff, pos,BUFSIZ); \
180
+    pos += smax;\
180 181
   }
181 182
 
182 183
 const char *sislangs[] = {"UNKNOWN", "UK English","French", "German", "Spanish", "Italian", "Swedish", "Danish", "Norwegian", "Finnish", "American", "Swiss French", "Swiss German", "Portuguese", "Turkish", "Icelandic", "Russian", "Hungarian", "Dutch", "Belgian Flemish", "Australian English", "Belgian French", "Austrian German", "New Zealand English", "International French", "Czech", "Slovak", "Polish", "Slovenian", "Taiwanese Chinese", "Hong Kong Chinese", "PRC Chinese", "Japanese", "Thai", "Afrikaans", "Albanian", "Amharic", "Arabic", "Armenian", "Tagalog", "Belarussian", "Bengali", "Bulgarian", "Burmese", "Catalan", "Croation", "Canadian English", "International English", "South African English", "Estonian", "Farsi", "Canadian French", "Gaelic", "Georgian", "Greek", "Cyprus Greek", "Gujarati", "Hebrew", "Hindi", "Indonesian", "Irish", "Swiss Italian", "Kannada", "Kazakh", "Kmer", "Korean", "Lao", "Latvian", "Lithuanian", "Macedonian", "Malay", "Malayalam", "Marathi", "Moldovian", "Mongolian", "Norwegian Nynorsk", "Brazilian Portuguese", "Punjabi", "Romanian", "Serbian", "Sinhalese", "Somali", "International Spanish", "American Spanish", "Swahili", "Finland Swedish", "Reserved", "Tamil", "Telugu", "Tibetan", "Tigrinya", "Cyprus Turkish", "Turkmen", "Ukrainian", "Urdu", "Reserved", "Vietnamese", "Welsh", "Zulu", "Other"};
183 184
 #define MAXLANG (sizeof(sislangs)/sizeof(sislangs[0]))
184 185
 
185
-static char *getsistring(FILE *f, uint32_t ptr, uint32_t len) {
186
+static char *getsistring(fmap_t *map, uint32_t ptr, uint32_t len) {
186 187
   char *name;
187 188
   uint32_t i;
188 189
 
... ...
@@ -193,8 +180,7 @@ static char *getsistring(FILE *f, uint32_t ptr, uint32_t len) {
193 193
     cli_dbgmsg("SIS: OOM\n");
194 194
     return NULL;
195 195
   }
196
-  fseek(f, ptr, SEEK_SET);
197
-  if (fread(name, len, 1, f)!=1) {
196
+  if (fmap_readn(map, name, ptr, len) != len) {
198 197
     cli_dbgmsg("SIS: Unable to read string\n");
199 198
     free(name);
200 199
     return NULL;
... ...
@@ -204,33 +190,31 @@ static char *getsistring(FILE *f, uint32_t ptr, uint32_t len) {
204 204
   return name;
205 205
 }
206 206
 
207
-static int spamsisnames(FILE *f, uint16_t langs, const char **alangs) {
208
-  uint32_t *lens, *ptrs;
207
+static int spamsisnames(fmap_t *map, size_t pos, uint16_t langs, const char **alangs) {
208
+  const uint32_t *ptrs;
209
+  const uint32_t *lens;
209 210
   unsigned int j;
210 211
 
211
-  if (!(lens = cli_malloc(sizeof(uint32_t) * langs * 2))) {
212
-    cli_dbgmsg("SIS: OOM\n");
213
-    return 0;
214
-  }
215
-  if (fread(lens, sizeof(uint32_t) * langs * 2, 1, f)!=1) {
212
+  const uint32_t len = sizeof(uint32_t) * langs * 2;
213
+
214
+  if (!(lens = fmap_need_off(map, pos, len))) {
216 215
     cli_dbgmsg("SIS: Unable to read lengths and pointers\n");
217
-    free(lens);
218 216
     return 1;
219 217
   }
220 218
   ptrs=&lens[langs];
221 219
 
222 220
   for (j=0; j<langs; j++) {
223
-    char *name = getsistring(f,EC32(ptrs[j]),EC32(lens[j]));
221
+    char *name = getsistring(map,EC32(ptrs[j]),EC32(lens[j]));
224 222
     if (name) {
225 223
       cli_dbgmsg("\t%s (%s - @%x, len %d)\n", name, alangs[j], EC32(ptrs[j]), EC32(lens[j]));
226 224
       free(name);
227 225
     }
228 226
   }
229
-  free(lens);
227
+  fmap_unneed_off(map, pos, len);
230 228
   return 1;
231 229
 }
232 230
 
233
-static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
231
+static int real_scansis(cli_ctx *ctx, const char *tmpd) {
234 232
   struct {
235 233
     uint16_t filesum;
236 234
     uint16_t langs;
... ...
@@ -257,11 +241,13 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
257 257
     uint32_t nspace;
258 258
   } sis;
259 259
   const char **alangs;
260
-  uint16_t *llangs;
260
+  const uint16_t *llangs;
261 261
   unsigned int i, sleft=0, smax=0, umped=0;
262 262
   uint8_t compd, buff[BUFSIZ];
263
+  size_t pos;
264
+  fmap_t *map = *ctx->fmap;
263 265
 
264
-  if (fread(&sis,sizeof(sis),1,f)!=1) {
266
+  if (fmap_readn(map, &sis, 16, sizeof(sis)) != sizeof(sis)) {
265 267
     cli_dbgmsg("SIS: Unable to read header\n");
266 268
     return CL_CLEAN;
267 269
   }
... ...
@@ -284,31 +270,26 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
284 284
     cli_dbgmsg("SIS: Too many or too few languages found\n");
285 285
     return CL_CLEAN;
286 286
   }
287
-  fseek(f, sis.plangs, SEEK_SET);
288
-  if (!(llangs=cli_malloc(sis.langs * sizeof(uint16_t)))) {
289
-    cli_dbgmsg("SIS: OOM\n");
290
-    return CL_CLEAN;
291
-  }
292
-  if (fread(llangs, sis.langs * sizeof(uint16_t), 1, f)!=1) {
287
+
288
+  pos = sis.plangs;
289
+
290
+  if (!(llangs = fmap_need_off_once(map, pos, sis.langs * sizeof(uint16_t)))) {
293 291
     cli_dbgmsg("SIS: Unable to read languages\n");
294
-    free(llangs);
295 292
     return CL_CLEAN;
296 293
   }
294
+  pos += sis.langs * sizeof(uint16_t);
297 295
   if (!(alangs=cli_malloc(sis.langs * sizeof(char *)))) {
298 296
     cli_dbgmsg("SIS: OOM\n");
299
-    free(llangs);
300 297
     return CL_CLEAN;
301 298
   }
302 299
   for (i = 0; i< sis.langs; i++)
303 300
     alangs[i]=EC32(llangs[i])<MAXLANG ? sislangs[EC32(llangs[i])] : sislangs[0];
304
-  free(llangs);
305 301
 
306 302
   if (!sis.pnames) {
307 303
     cli_dbgmsg("SIS: Application without a name?\n");
308 304
   } else {
309
-    fseek(f, sis.pnames, SEEK_SET);
310 305
     cli_dbgmsg("SIS: Application name:\n");
311
-    if (!spamsisnames(f, sis.langs, alangs)) {
306
+    if (!spamsisnames(map, sis.pnames, sis.langs, alangs)) {
312 307
       free(alangs);
313 308
       return CL_EMEM;
314 309
     }
... ...
@@ -317,9 +298,8 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
317 317
   if (!sis.pcaps) {
318 318
     cli_dbgmsg("SIS: Application without capabilities?\n");
319 319
   } else {
320
-    fseek(f, sis.pcaps, SEEK_SET);
321 320
     cli_dbgmsg("SIS: Provides:\n");
322
-    if (!spamsisnames(f, sis.langs, alangs)) {
321
+    if (!spamsisnames(map, sis.pcaps, sis.langs, alangs)) {
323 322
       free(alangs);
324 323
       return CL_EMEM;
325 324
     }
... ...
@@ -336,13 +316,14 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
336 336
 	uint16_t verlo;
337 337
 	uint32_t versub;
338 338
       } dep;
339
-      
340
-      fseek(f, sis.pdeps + i*(sizeof(dep) + sis.langs*2*sizeof(uint32_t)), SEEK_SET);
341
-      if (fread(&dep, sizeof(dep), 1, f)!=1) {
339
+
340
+      pos = sis.pdeps + i*(sizeof(dep) + sis.langs*2*sizeof(uint32_t));
341
+      if (fmap_readn(map, &dep, pos, sizeof(dep)) != sizeof(dep)) {
342 342
 	cli_dbgmsg("SIS: Unable to read dependencies\n");
343 343
       } else {
344
+	pos += sizeof(dep);
344 345
 	cli_dbgmsg("\tUID: %x v. %d.%d.%d\n\taka:\n", EC32(dep.uid), EC16(dep.verhi), EC16(dep.verlo), EC32(dep.versub));
345
-	if (!spamsisnames(f, sis.langs, alangs)) {
346
+	if (!spamsisnames(map, pos, sis.langs, alangs)) {
346 347
 	  free(alangs);
347 348
 	  return CL_EMEM;
348 349
 	}
... ...
@@ -353,7 +334,7 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
353 353
   compd = !(sis.flags & 0x0008);
354 354
   cli_dbgmsg("SIS: Package is%s compressed\n", (compd)?"":" not");
355 355
 
356
-  fseek(f, sis.pfiles, SEEK_SET);
356
+  pos = sis.pfiles;
357 357
   for (i=0; i<sis.files; i++) {
358 358
     uint32_t pkgtype, fcount=1;
359 359
     uint32_t j;
... ...
@@ -411,16 +392,14 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
411 411
 	sftype = "unknown";
412 412
       }
413 413
       cli_dbgmsg("SIS: File details:\n\tOptions: %d\n\tType: %s\n", options, sftype);
414
-      fpos = ftell(f);
415
-      if ((fn=getsistring(f, psname, ssname))) {
414
+      if ((fn=getsistring(map, psname, ssname))) {
416 415
 	cli_dbgmsg("\tOriginal filename: %s\n", fn);
417 416
 	free(fn);
418 417
       }
419
-      if ((fn=getsistring(f, pdname, sdname))) {
418
+      if ((fn=getsistring(map,  pdname, sdname))) {
420 419
 	cli_dbgmsg("\tInstalled to: %s\n", fn);
421 420
 	free(fn);
422 421
       }
423
-      fseek(f,fpos,SEEK_SET);
424 422
 
425 423
       if (!(ptrs=cli_malloc(fcount*sizeof(uint32_t)*3))) {
426 424
 	cli_dbgmsg("\tOOM\n");
... ...
@@ -435,15 +414,15 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
435 435
 	GETD2(ptrs[j]);
436 436
       for (j=0; j<fcount; j++)
437 437
 	GETD2(olens[j]);
438
-      
438
+
439 439
       if (ftype!=FTnull) {
440 440
 	char ofn[1024];
441 441
 	int fd;
442 442
 
443
-	fpos = ftell(f);
444
-
445 443
 	for (j=0; j<fcount; j++) {
446
-	  void *comp, *decomp;
444
+	  void *decomp;
445
+	  const void *comp;
446
+	  const void *decompp = NULL;
447 447
 	  uLongf olen;
448 448
 
449 449
 	  if (!lens[j]) {
... ...
@@ -452,16 +431,9 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
452 452
 	  }
453 453
 	  if (cli_checklimits("sis", ctx,lens[j], 0, 0)!=CL_CLEAN) continue;
454 454
 	  cli_dbgmsg("\tUnpacking lang#%d - ptr:%x csize:%x osize:%x\n", j, ptrs[j], lens[j], olens[j]);
455
-	  if (!(comp=cli_malloc(lens[j]))) {
456
-	    cli_dbgmsg("\tOOM\n");
457
-	    free(ptrs);
458
-	    free(alangs);
459
-	    return CL_CLEAN;
460
-	  }
461
-	  fseek(f,ptrs[j],SEEK_SET);
462
-	  if (fread(comp, lens[j], 1, f)!=1) {
455
+
456
+	  if (!(comp = fmap_need_off_once(map, ptrs[j], lens[j]))) {
463 457
 	    cli_dbgmsg("\tSkipping ghost or otherwise out of archive file\n");
464
-	    free(comp);
465 458
 	    continue;
466 459
 	  }
467 460
 	  if (compd) {
... ...
@@ -470,27 +442,24 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
470 470
 	    else if (cli_checklimits("sis", ctx, olens[j], 0, 0)==CL_CLEAN)
471 471
 	      olen=olens[j];
472 472
 	    else {
473
-	      free(comp);
474 473
 	      continue;
475 474
 	    }
476
-	      
475
+
477 476
 	    if (!(decomp=cli_malloc(olen))) {
478 477
 	      cli_dbgmsg("\tOOM\n");
479
-	      free(comp);
480 478
 	      free(ptrs);
481 479
 	      free(alangs);
482 480
 	      return CL_CLEAN;
483 481
 	    }
484 482
 	    if (uncompress(decomp, &olen, comp, lens[j])!=Z_OK) {
485 483
 	      cli_dbgmsg("\tUnpacking failure\n");
486
-	      free(comp);
487 484
 	      free(decomp);
488 485
 	      continue;
489 486
 	    }
490
-	    free(comp);
487
+	    decompp = decomp;
491 488
 	  } else {
492 489
 	    olen = lens[j];
493
-	    decomp = comp;
490
+	    decompp = comp;
494 491
 	  }
495 492
 	  snprintf(ofn, 1024, "%s"PATHSEP"sis%02d", tmpd, umped);
496 493
 	  ofn[1023]='\0';
... ...
@@ -501,7 +470,7 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
501 501
 	    free(alangs);
502 502
 	    return CL_ECREAT;
503 503
 	  }
504
-	  if (cli_writen(fd, decomp, olen)!=(int)olen) {
504
+	  if (cli_writen(fd, decompp, olen)!=(int)olen) {
505 505
 	    close(fd);
506 506
 	    free(decomp);
507 507
 	    free(ptrs);
... ...
@@ -518,7 +487,6 @@ static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
518 518
 	  close(fd);
519 519
 	  umped++;
520 520
 	}
521
-	fseek(f,fpos,SEEK_SET);
522 521
       }
523 522
       free(ptrs);
524 523
       fcount=2*sizeof(uint32_t);
... ...
@@ -571,7 +539,8 @@ const char *sisfields[] = {"Invalid", "String", "Array", "Compressed", "Version"
571 571
 #define HERE printf("here\n"),abort();
572 572
 
573 573
 struct SISTREAM {
574
-  FILE *f;
574
+  fmap_t *map;
575
+  size_t pos;
575 576
   uint8_t buff[BUFSIZ];
576 577
   uint32_t smax;
577 578
   uint32_t sleft;
... ...
@@ -582,10 +551,13 @@ struct SISTREAM {
582 582
 
583 583
 static inline int getd(struct SISTREAM *s, uint32_t *v) {
584 584
   if (s->sleft<4) {
585
+    int nread;
585 586
     memcpy(s->buff, s->buff + s->smax - s->sleft, s->sleft);
586
-    if ((s->sleft=s->smax=fread(&s->buff[s->sleft], 1, BUFSIZ - s->sleft, s->f) + s->sleft)<4) {
587
+    nread = fmap_readn(s->map, &s->buff[s->sleft], s->pos, BUFSIZ - s->sleft);
588
+    if ((s->sleft=s->smax=nread + s->sleft)<4) {
587 589
       return 1;
588 590
     }
591
+    s->pos += nread;
589 592
   }
590 593
   *v = cli_readint32(&s->buff[s->smax - s->sleft]);
591 594
   s->sleft-=4;
... ...
@@ -596,7 +568,7 @@ static inline int getsize(struct SISTREAM *s) {
596 596
   uint32_t *fsize = &s->fsize[s->level];
597 597
   if(getd(s, fsize) || !*fsize || (*fsize)>>31 || (s->level && *fsize > s->fsize[s->level-1] * 2)) return 1;
598 598
   /* To handle crafted archives we allow the content to overflow the container but only up to 2 times the container size */
599
-  s->fnext[s->level] = ftell(s->f) - s->sleft + *fsize;
599
+  s->fnext[s->level] = s->pos - s->sleft + *fsize;
600 600
   return 0;
601 601
 }
602 602
 
... ...
@@ -621,7 +593,7 @@ static inline int skip(struct SISTREAM *s, uint32_t size) {
621 621
     seekto = size - s->sleft;
622 622
     if (seekto<0) /* in case sizeof(long)==sizeof(uint32_t) */
623 623
       return 1;
624
-    fseek(s->f, seekto, SEEK_CUR);
624
+    s->pos += seekto;
625 625
     /*     s->sleft = s->smax = fread(s->buff,1,BUFSIZ,s->f); */
626 626
     s->sleft = s->smax = 0;
627 627
   }
... ...
@@ -633,19 +605,20 @@ static inline int skipthis(struct SISTREAM *s) {
633 633
 }
634 634
 
635 635
 static inline void seeknext(struct SISTREAM *s) {
636
-  fseek(s->f, s->fnext[s->level], SEEK_SET);
636
+  s->pos = s->fnext[s->level];
637 637
   /*   s->sleft = s->smax = fread(s->buff,1,BUFSIZ,s->f); */
638 638
   s->sleft = s->smax = 0;
639 639
 }
640 640
 
641 641
 
642
-static int real_scansis9x(FILE *f, cli_ctx *ctx, const char *tmpd) {
642
+static int real_scansis9x(cli_ctx *ctx, const char *tmpd) {
643 643
   struct SISTREAM stream;
644 644
   struct SISTREAM *s = &stream;
645 645
   uint32_t field, optst[]={T_CONTROLLERCHECKSUM, T_DATACHECKSUM, T_COMPRESSED};
646 646
   unsigned int i;
647 647
 
648
-  s->f = f;
648
+  s->map = *ctx->fmap;
649
+  s->pos = 0;
649 650
   s->smax = 0;
650 651
   s->sleft = 0;
651 652
   s->level = 0;
... ...
@@ -691,7 +664,7 @@ static int real_scansis9x(FILE *f, cli_ctx *ctx, const char *tmpd) {
691 691
 
692 692
 	  s->level++;
693 693
 	  while (s->fsize[s->level-1] && !getsize(s)) { /* FOREACH DATA::ARRAY::DATAUNIT[x]::ARRAY::FILEDATA */
694
-	    uint32_t usize, usizeh;
694
+	    uint32_t usize, usizeh, len;
695 695
 	    void *src, *dst;
696 696
 	    char tempf[1024];
697 697
 	    uLongf uusize;
... ...
@@ -710,15 +683,18 @@ static int real_scansis9x(FILE *f, cli_ctx *ctx, const char *tmpd) {
710 710
 	      cli_dbgmsg("SIS: File is%s compressed - size %x -> %x\n", (field)?"":" not", s->fsize[s->level], usize);
711 711
 	      snprintf(tempf, 1024, "%s"PATHSEP"sis9x%02d", tmpd, i++);
712 712
 	      tempf[1023]='\0';
713
-	      fseek(s->f, -(long)s->sleft, SEEK_CUR);
713
+	      s->pos -= (long)s->sleft;
714 714
 	      s->sleft = s->smax = 0;
715 715
 
716 716
 	      if (cli_checklimits("sis", ctx,ALIGN4(s->fsize[s->level]), 0, 0)!=CL_CLEAN) break;
717 717
 	      if (!(src=cli_malloc(ALIGN4(s->fsize[s->level])))) break;
718
-	      if (fread(src, ALIGN4(s->fsize[s->level]),1,s->f) != 1) {
718
+
719
+	      len = ALIGN4(s->fsize[s->level]);
720
+	      if (fmap_readn(s->map, src, s->pos, len) != len) {
719 721
 		free(src);
720 722
 		break;
721 723
 	      }
724
+	      s->pos += len;
722 725
 
723 726
 	      if(field) { /* compressed */
724 727
 		int zresult;
... ...
@@ -23,6 +23,6 @@
23 23
 
24 24
 #include "others.h"
25 25
 
26
-int cli_scansis(int desc, cli_ctx *ctx);
26
+int cli_scansis(cli_ctx *ctx);
27 27
 
28 28
 #endif
... ...
@@ -45,76 +45,79 @@
45 45
 #define special_endian_convert_16(v) be16_to_host(v)
46 46
 #define special_endian_convert_32(v) be32_to_host(v)
47 47
 
48
-int cli_check_mydoom_log(int desc, cli_ctx *ctx)
48
+int cli_check_mydoom_log(cli_ctx *ctx)
49 49
 {
50
-	uint32_t record[8], check;
51
-	int i, retval=CL_VIRUS, j;
50
+	const uint32_t *record;
51
+	uint32_t check, key;
52
+	fmap_t *map = *ctx->fmap;
53
+	unsigned int blocks = map->len / (8*4);
52 54
 
53 55
     cli_dbgmsg("in cli_check_mydoom_log()\n");
54
-
55
-    /* Check upto the first five records in the file */
56
-    for (j=0 ; j<5 ; j++) {
57
-	if (cli_readn(desc, &record, 32) != 32) {
58
-	    break;
59
-	}
60
-	if(!j && record[0] == 0xffffffff) /* bb#1241 */
61
-	    return CL_CLEAN;
62
-
63
-	/* Decode the key */
64
-	record[0] = ~ntohl(record[0]);
65
-	cli_dbgmsg("Mydoom: key: %d\n", record[0]);
66
-	check = 0;
67
-	for (i=1 ; i<8; i++) {
68
-	    record[i] = ntohl(record[i]) ^ record[0];
69
-	    check += record[i];
70
-	}
71
-	cli_dbgmsg("Mydoom: check: %d\n", ~check);
72
-	if ((~check) != record[0]) {
56
+    if(blocks<2)
57
+	return CL_CLEAN;
58
+    if(blocks>5)
59
+	blocks = 5;
60
+
61
+    record = fmap_need_off_once(map, 0, 8*4*blocks);
62
+    if(!record)
63
+	return CL_CLEAN;
64
+    while(blocks) { /* This wasn't probably intended but that's what the current code does anyway */
65
+	if(record[--blocks] == 0xffffffff)
73 66
 	    return CL_CLEAN;
74
-	}
75 67
     }
76 68
 
77
-    if (j < 2) {
78
-	retval = CL_CLEAN;
79
-    } else if (retval==CL_VIRUS) {
80
-	*ctx->virname = "Heuristics.Worm.Mydoom.M.log";
81
-    }
82
-
83
-    return retval;
69
+    key = ~be32_to_host(record[0]);
70
+    check = (be32_to_host(record[1])^key) +
71
+	(be32_to_host(record[2])^key) +
72
+	(be32_to_host(record[3])^key) +
73
+	(be32_to_host(record[4])^key) +
74
+	(be32_to_host(record[5])^key) +
75
+	(be32_to_host(record[6])^key) +
76
+	(be32_to_host(record[7])^key);
77
+    if ((~check) != key)
78
+	return CL_CLEAN;
79
+
80
+    key = ~be32_to_host(record[8]);
81
+    check = (be32_to_host(record[9])^key) +
82
+	(be32_to_host(record[10])^key) +
83
+	(be32_to_host(record[11])^key) +
84
+	(be32_to_host(record[12])^key) +
85
+	(be32_to_host(record[13])^key) +
86
+	(be32_to_host(record[14])^key) +
87
+	(be32_to_host(record[15])^key);
88
+    if ((~check) != key)
89
+	return CL_CLEAN;
90
+
91
+    *ctx->virname = "Heuristics.Worm.Mydoom.M.log";
92
+    return CL_VIRUS;
84 93
 }
85 94
 
86
-static int jpeg_check_photoshop_8bim(int fd, cli_ctx *ctx)
95
+static int jpeg_check_photoshop_8bim(cli_ctx *ctx, off_t *off)
87 96
 {
88
-	unsigned char bim[5];
97
+	const unsigned char *buf;
89 98
 	uint16_t id, ntmp;
90 99
 	uint8_t nlength;
91 100
 	uint32_t size;
92
-	off_t offset;
101
+	off_t offset = *off;
93 102
 	int retval;
103
+	fmap_t *map = *ctx->fmap;
94 104
 
95
-	if (cli_readn(fd, bim, 4) != 4) {
105
+	if(!(buf = fmap_need_off_once(map, offset, 4 + 2 + 1))) {
96 106
 		cli_dbgmsg("read bim failed\n");
97 107
 		return -1;
98 108
 	}
99
-
100
-	if (memcmp(bim, "8BIM", 4) != 0) {
101
-		bim[4] = '\0';
102
-		cli_dbgmsg("missed 8bim: %s\n", bim);
109
+	if (memcmp(buf, "8BIM", 4) != 0) {
110
+		cli_dbgmsg("missed 8bim\n");
103 111
 		return -1;
104 112
 	}
105 113
 
106
-	if (cli_readn(fd, &id, 2) != 2) {
107
-		return -1;
108
-	}
109
-	id = special_endian_convert_16(id);
114
+	id = (uint16_t)buf[4] | ((uint16_t)buf[5]<<8);
110 115
 	cli_dbgmsg("ID: 0x%.4x\n", id);
111
-	if (cli_readn(fd, &nlength, 1) != 1) {
112
-		return -1;
113
-	}
116
+	nlength = buf[6];
114 117
 	ntmp = nlength + ((((uint16_t)nlength)+1) & 0x01);
115
-	lseek(fd, ntmp, SEEK_CUR);
116
-	
117
-	if (cli_readn(fd, &size, 4) != 4) {
118
+	offset += 4 + 2 + 1 + ntmp;
119
+
120
+	if (fmap_readn(map, &size, offset, 4) != 4) {
118 121
 		return -1;
119 122
 	}
120 123
 	size = special_endian_convert_32(size);
... ...
@@ -124,49 +127,46 @@ static int jpeg_check_photoshop_8bim(int fd, cli_ctx *ctx)
124 124
 	if ((size & 0x01) == 1) {
125 125
 		size++;
126 126
 	}
127
+
128
+	*off = offset + 4 + size;
127 129
 	/* Is it a thumbnail image */
128 130
 	if ((id != 0x0409) && (id != 0x040c)) {
129 131
 		/* No - Seek past record */
130
-		lseek(fd, size, SEEK_CUR);
131 132
 		return 0;
132 133
 	}
133 134
 
134 135
 	cli_dbgmsg("found thumbnail\n");
135
-	/* Check for thumbmail image */
136
-	offset = lseek(fd, 0, SEEK_CUR);
137
-
138 136
 	/* Jump past header */
139
-	lseek(fd, 28, SEEK_CUR);
137
+	offset += 4 + 28;
140 138
 
141
-	retval = cli_check_jpeg_exploit(fd, ctx);
139
+	retval = cli_check_jpeg_exploit(ctx, offset);
142 140
 	if (retval == 1) {
143 141
 		cli_dbgmsg("Exploit found in thumbnail\n");
144 142
 	}
145
-	lseek(fd, offset+size, SEEK_SET);
146
-
147 143
 	return retval;
148 144
 }
149 145
 
150
-static int jpeg_check_photoshop(int fd, cli_ctx *ctx)
146
+static int jpeg_check_photoshop(cli_ctx *ctx, off_t offset)
151 147
 {
152 148
 	int retval;
153
-	unsigned char buffer[14];
154
-	off_t old, new;
149
+	const unsigned char *buffer;
150
+	off_t old;
151
+	fmap_t *map = *ctx->fmap;
155 152
 
156
-	if (cli_readn(fd, buffer, 14) != 14) {
153
+	if(!(buffer = fmap_need_off_once(map, offset, 14))) {
157 154
 		return 0;
158 155
 	}
159 156
 
160 157
 	if (memcmp(buffer, "Photoshop 3.0", 14) != 0) {
161 158
 		return 0;
162 159
 	}
160
+	offset += 14;
163 161
 
164 162
 	cli_dbgmsg("Found Photoshop segment\n");
165 163
 	do {
166
-		old = lseek(fd, 0, SEEK_CUR);
167
-		retval = jpeg_check_photoshop_8bim(fd, ctx);
168
-		new = lseek(fd, 0, SEEK_CUR);
169
-		if(new <= old)
164
+		old = offset;
165
+		retval = jpeg_check_photoshop_8bim(ctx, &offset);
166
+		if(offset <= old)
170 167
 			break;
171 168
 	} while (retval == 0);
172 169
 
... ...
@@ -176,35 +176,33 @@ static int jpeg_check_photoshop(int fd, cli_ctx *ctx)
176 176
 	return retval;
177 177
 }
178 178
 
179
-int cli_check_jpeg_exploit(int fd, cli_ctx *ctx)
179
+int cli_check_jpeg_exploit(cli_ctx *ctx, off_t offset)
180 180
 {
181
-	unsigned char buffer[4];
182
-	off_t offset;
181
+	const unsigned char *buffer;
183 182
 	int retval;
184
-
183
+	fmap_t *map = *ctx->fmap;
185 184
 
186 185
 	cli_dbgmsg("in cli_check_jpeg_exploit()\n");
187 186
 	if(ctx->recursion > ctx->engine->maxreclevel)
188 187
 	    return CL_EMAXREC;
189 188
 
190
-	if (cli_readn(fd, buffer, 2) != 2) {
189
+	if(!(buffer = fmap_need_off_once(map, offset, 2)))
191 190
 		return 0;
192
-	}
193
-
194 191
 	if ((buffer[0] != 0xff) || (buffer[1] != 0xd8)) {
195 192
 		return 0;
196 193
 	}
197
-
194
+	offset += 2;
198 195
 	for (;;) {
199
-		if ((retval=cli_readn(fd, buffer, 4)) != 4) {
196
+		off_t new_off;
197
+		if(!(buffer = fmap_need_off_once(map, offset, 4))) {
200 198
 			return 0;
201 199
 		}
202 200
 		/* Check for multiple 0xFF values, we need to skip them */
203 201
 		if ((buffer[0] == 0xff) && (buffer[1] == 0xff)) {
204
-			lseek(fd, -3, SEEK_CUR);
202
+			offset++;
205 203
 			continue;
206 204
 		}
207
-
205
+		offset += 4;
208 206
 		if ((buffer[0] == 0xff) && (buffer[1] == 0xfe)) {
209 207
 			if (buffer[2] == 0x00) {
210 208
 				if ((buffer[3] == 0x00) || (buffer[3] == 0x01)) {
... ...
@@ -220,25 +218,22 @@ int cli_check_jpeg_exploit(int fd, cli_ctx *ctx)
220 220
 			return 0;
221 221
 		}
222 222
 
223
-		offset = ((unsigned int) buffer[2] << 8) + buffer[3];
224
-		if (offset < 2) {
223
+		new_off = ((unsigned int) buffer[2] << 8) + buffer[3];
224
+		if (new_off < 2) {
225 225
 			return -1;
226 226
 		}
227
-		offset -= 2;
228
-		offset += lseek(fd, 0, SEEK_CUR);
227
+		new_off -= 2;
228
+		new_off += offset;
229 229
 
230 230
 		if (buffer[1] == 0xed) {
231 231
 			/* Possible Photoshop file */
232 232
 			ctx->recursion++;
233
-			retval=jpeg_check_photoshop(fd, ctx);
233
+			retval=jpeg_check_photoshop(ctx, offset);
234 234
 			ctx->recursion--;
235 235
 			if (retval != 0)
236 236
 				return retval;
237 237
 		}
238
-
239
-		if (lseek(fd, offset, SEEK_SET) != offset) {
240
-			return -1;
241
-		}
238
+		offset = new_off;
242 239
 	}
243 240
 }
244 241
 
... ...
@@ -250,103 +245,85 @@ static uint32_t riff_endian_convert_32(uint32_t value, int big_endian)
250 250
 		return le32_to_host(value);
251 251
 }
252 252
 
253
-static int riff_read_chunk(int fd, int big_endian, int rec_level)
253
+static int riff_read_chunk(fmap_t *map, off_t *offset, int big_endian, int rec_level)
254 254
 {
255
-	uint32_t chunk_id;
255
+	const uint32_t *buf;
256 256
 	uint32_t chunk_size;
257
-	int length;
258
-	uint32_t list_type;
259
-	off_t offset, cur_offset;
257
+	off_t cur_offset = *offset;
260 258
 
261 259
 	if (rec_level > 1000) {
262 260
 		cli_dbgmsg("riff_read_chunk: recursion level exceeded\n");
263 261
 		return 0;
264 262
 	}
265
-	
266
-	length = sizeof(uint32_t);
267
-	if (cli_readn(fd, &chunk_id, length) != length) {
268
-		return 0;
269
-	}
270
-	if (cli_readn(fd, &chunk_size, length) != length) {
271
-		return 0;
272
-	}
273
-	chunk_size = riff_endian_convert_32(chunk_size, big_endian);
274 263
 
275
-	if(!memcmp(&chunk_id, "anih", 4) && chunk_size != 36)
264
+	if(!(buf = fmap_need_off_once(map, cur_offset, 4*2)))
265
+	    return 0;
266
+	cur_offset += 4*2;
267
+	chunk_size = riff_endian_convert_32(buf[1], big_endian);
268
+
269
+	if(!memcmp(buf, "anih", 4) && chunk_size != 36)
276 270
 	    return 2;
277 271
 
278
-	if (memcmp(&chunk_id, "RIFF", 4) == 0) {
272
+	if (memcmp(buf, "RIFF", 4) == 0) {
279 273
 		return 0;
280
-	} else if (memcmp(&chunk_id, "RIFX", 4) == 0) {
274
+	} else if (memcmp(buf, "RIFX", 4) == 0) {
281 275
 		return 0;
282 276
 	}
283 277
 	
284
-	if ((memcmp(&chunk_id, "LIST", 4) == 0) ||
285
-		 (memcmp(&chunk_id, "PROP", 4) == 0) ||
286
-		 (memcmp(&chunk_id, "FORM", 4) == 0) ||
287
-		 (memcmp(&chunk_id, "CAT ", 4) == 0)) {
288
-		if (cli_readn(fd, &list_type, sizeof(list_type)) != sizeof(list_type)) {
278
+	if ((memcmp(buf, "LIST", 4) == 0) ||
279
+		 (memcmp(buf, "PROP", 4) == 0) ||
280
+		 (memcmp(buf, "FORM", 4) == 0) ||
281
+		 (memcmp(buf, "CAT ", 4) == 0)) {
282
+		if (!fmap_need_ptr_once(map, buf+2, 4)) {
289 283
 			cli_dbgmsg("riff_read_chunk: read list type failed\n");
290 284
 			return 0;
291 285
 		}
292
-		return riff_read_chunk(fd, big_endian, ++rec_level);	
286
+		*offset = cur_offset+4;
287
+		return riff_read_chunk(map, offset, big_endian, ++rec_level);
293 288
 	}
294 289
 	
295
-	cur_offset = lseek(fd, 0, SEEK_CUR);
296
-	offset = cur_offset + chunk_size;
297
-	/* Check for odd alignment */
298
-	if ((offset & 0x01) == 1) {
299
-		offset++;
300
-	}
301
-	if (offset < cur_offset) {
290
+	*offset = cur_offset + chunk_size + (chunk_size&1);
291
+	if (*offset < cur_offset) {
302 292
 		return 0;
303 293
 	}
294
+	/* FIXME: WTF!?
304 295
 	if (lseek(fd, offset, SEEK_SET) != offset) {
305 296
 		return 2;
306 297
 	}
298
+	*/
307 299
 	return 1;
308 300
 }
309 301
 
310
-int cli_check_riff_exploit(int fd)
302
+int cli_check_riff_exploit(cli_ctx *ctx)
311 303
 {
312
-	uint32_t chunk_id;
313
-	uint32_t chunk_size;
314
-	uint32_t form_type;
315
-	int length, big_endian, retval;
304
+	const uint32_t *buf;
305
+	int big_endian, retval;
316 306
 	off_t offset;
307
+	fmap_t *map = *ctx->fmap;
317 308
 	
318 309
 	cli_dbgmsg("in cli_check_riff_exploit()\n");
319 310
 
320
-	length = sizeof(uint32_t);
321
-	if (cli_readn(fd, &chunk_id, length) != length) {
322
-		return 0;
323
-	}
324
-	if (cli_readn(fd, &chunk_size, length) != length) {
325
-		return 0;
326
-	}
327
-	if (cli_readn(fd, &form_type, length) != length) {
328
-		return 0;
329
-	}
330
-	
331
-	if (memcmp(&chunk_id, "RIFF", 4) == 0) {
311
+	if(!(buf = fmap_need_off_once(map, 0, 4*3)))
312
+	    return 0;
313
+
314
+	if (memcmp(buf, "RIFF", 4) == 0) {
332 315
 		big_endian = FALSE;
333
-	} else if (memcmp(&chunk_id, "RIFX", 4) == 0) {
316
+	} else if (memcmp(buf, "RIFX", 4) == 0) {
334 317
 		big_endian = TRUE;
335 318
 	} else {
336 319
 		/* Not a RIFF file */
337 320
 		return 0;
338 321
 	}
339 322
 
340
-	if (memcmp(&form_type, "ACON", 4) != 0) {
323
+	if (memcmp(&buf[2], "ACON", 4) != 0) {
341 324
 		/* Only scan MS animated icon files */
342 325
 		/* There is a *lot* of broken software out there that produces bad RIFF files */
343 326
 		return 0;
344 327
 	}
345 328
 
346
-	chunk_size = riff_endian_convert_32(chunk_size, big_endian);
347
-
329
+	offset = 4*3;
348 330
 	do {
349
-		retval = riff_read_chunk(fd, big_endian, 1);
331
+		retval = riff_read_chunk(map, &offset, big_endian, 1);
350 332
 	} while (retval == 1);
351 333
 
352 334
 	return retval;
... ...
@@ -33,9 +33,9 @@ struct swizz_stats {
33 33
 	int entries;
34 34
 };
35 35
 
36
-int cli_check_mydoom_log(int desc, cli_ctx *ctx);
37
-int cli_check_jpeg_exploit(int fd, cli_ctx *ctx);
38
-int cli_check_riff_exploit(int fd);
36
+int cli_check_mydoom_log(cli_ctx *ctx);
37
+int cli_check_jpeg_exploit(cli_ctx *ctx, off_t offset);
38
+int cli_check_riff_exploit(cli_ctx *ctx);
39 39
 void cli_detect_swizz_str(const unsigned char *str, uint32_t len, struct swizz_stats *stats, int blob);
40 40
 int cli_detect_swizz(struct swizz_stats *stats);
41 41
 
... ...
@@ -242,22 +242,12 @@ static const char *tagname(tag_id id)
242 242
 
243 243
 static int dumpscan(fmap_t *map, unsigned int offset, unsigned int size, const char *obj, int version, cli_ctx *ctx)
244 244
 {
245
-	int newfd, ret = CL_CLEAN;
246
-	unsigned int bread, sum = 0;
247
-	char buff[FILEBUFF];
248
-	char *name;
249
-
250
-    if(!(name = cli_gentemp(ctx->engine->tmpdir)))
251
-	return CL_EMEM;
252
-
253
-    if((newfd = open(name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) {
254
-	cli_errmsg("dumpscan: Can't create file %s\n", name);
255
-	free(name);
256
-	return CL_ECREAT;
257
-    }
245
+    int ret = CL_CLEAN;
246
+    char buff[16];
258 247
 
259
-    while((bread = fmap_readn(map, buff, offset, sizeof(buff))) > 0) {
260
-	if(!sum && ctx->img_validate) {
248
+    memset(buff, 0, sizeof(buff));
249
+    fmap_readn(map, buff, offset, sizeof(buff));
250
+    if(ctx->img_validate) {
261 251
 	    if(!memcmp(buff, "\xff\xd8", 2)) {
262 252
 		cli_dbgmsg("SWF: JPEG image data\n");
263 253
 	    } else if(!memcmp(buff, "\xff\xd9\xff\xd8", 4)) {
... ...
@@ -284,46 +274,10 @@ static int dumpscan(fmap_t *map, unsigned int offset, unsigned int size, const c
284 284
 		ret = CL_VIRUS;
285 285
 	    }
286 286
 	    if(ret == CL_VIRUS) {
287
-		close(newfd);
288
-		cli_unlink(name);
289
-		free(name);
290 287
 		return ret;
291 288
 	    }
292
-	}
293
-	if(sum + bread >= size) {
294
-	    if(cli_writen(newfd, buff, size - sum) == -1) {
295
-		cli_errmsg("dumpscan: Can't write to %s\n", name);
296
-		close(newfd);
297
-		cli_unlink(name);
298
-		free(name);
299
-		return CL_EWRITE;
300
-	    }
301
-	    break;
302
-	} else {
303
-	    if(cli_writen(newfd, buff, bread) == -1) {
304
-		cli_errmsg("cli_dumpscan: Can't write to %s\n", name);
305
-		close(newfd);
306
-		cli_unlink(name);
307
-		free(name);
308
-		return CL_EWRITE;
309
-	    }
310
-	}
311
-	sum += bread;
312
-	offset += bread;
313
-    }
314
-    cli_dbgmsg("SWF: %s data extracted to %s\n", obj, name);
315
-    lseek(newfd, 0, SEEK_SET);
316
-    if((ret = cli_magic_scandesc(newfd, ctx)) == CL_VIRUS)
317
-	cli_dbgmsg("cli_dumpscan: Infected with %s\n", *ctx->virname);
318
-
319
-    close(newfd);
320
-    if(!ctx->engine->keeptmp) {
321
-	if(cli_unlink(name)) {
322
-	    free(name);
323
-	    return CL_EUNLINK;
324
-	}
325 289
     }
326
-    free(name);
290
+    ret = cli_map_scandesc(map, offset, size, ctx);
327 291
     if(ctx->img_validate && ret == CL_EPARSE && SCAN_ALGO) {
328 292
 	*ctx->virname = "Heuristics.SWF.SuspectImage.E";
329 293
 	return CL_VIRUS;
... ...
@@ -38,9 +38,9 @@ static	char	const	rcsid[] = "$Id: tnef.c,v 1.41 2007/02/12 22:22:27 njh Exp $";
38 38
 #include "mbox.h"
39 39
 #include "tnef.h"
40 40
 
41
-static	int	tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length, off_t fsize);
42
-static	int	tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const char *dir, fileblob **fbref, off_t fsize);
43
-static	int	tnef_header(FILE *fp, uint8_t *part, uint16_t *type, uint16_t *tag, int32_t *length);
41
+static	int	tnef_message(fmap_t *map, off_t *pos, uint16_t type, uint16_t tag, int32_t length, off_t fsize);
42
+static	int	tnef_attachment(fmap_t *map, off_t *pos, uint16_t type, uint16_t tag, int32_t length, const char *dir, fileblob **fbref, off_t fsize);
43
+static	int	tnef_header(fmap_t *map, off_t *pos, uint8_t *part, uint16_t *type, uint16_t *tag, int32_t *length);
44 44
 
45 45
 #define	TNEF_SIGNATURE	0x223E9f78
46 46
 #define	LVL_MESSAGE	0x01
... ...
@@ -61,51 +61,38 @@ static	int	tnef_header(FILE *fp, uint8_t *part, uint16_t *type, uint16_t *tag, i
61 61
 #define	MIN_SIZE	(sizeof(uint32_t) + sizeof(uint16_t))
62 62
 
63 63
 int
64
-cli_tnef(const char *dir, int desc, cli_ctx *ctx)
64
+cli_tnef(const char *dir, cli_ctx *ctx)
65 65
 {
66 66
 	uint32_t i32;
67 67
 	uint16_t i16;
68 68
 	fileblob *fb;
69
-	int i, ret, alldone;
70
-	FILE *fp;
71
-	off_t fsize;
69
+	int ret, alldone;
70
+	off_t fsize, pos = 0;
72 71
 	struct stat statb;
73 72
 
74
-	lseek(desc, 0L, SEEK_SET);
75 73
 
76
-	if(fstat(desc, &statb) < 0) {
77
-		cli_errmsg("Can't fstat descriptor %d\n", desc);
78
-		return CL_ESTAT;
79
-	}
80
-	fsize = statb.st_size;
74
+	fsize = ctx->fmap[0]->len;
81 75
 
82 76
 	if(fsize < (off_t) MIN_SIZE) {
83 77
 		cli_dbgmsg("cli_tngs: file too small, ignoring\n");
84 78
 		return CL_CLEAN;
85 79
 	}
86 80
 
87
-	i = dup(desc);
88
-	if((fp = fdopen(i, "rb")) == NULL) {
89
-		cli_errmsg("Can't open descriptor %d\n", desc);
90
-		close(i);
91
-		return CL_EOPEN;
92
-	}
93
-
94
-	if(fread(&i32, sizeof(uint32_t), 1, fp) != 1) {
95
-		fclose(fp);
81
+	if (fmap_readn(*ctx->fmap, &i32, pos, sizeof(uint32_t)) != sizeof(uint32_t)) {
96 82
 		/* The file is at least MIN_SIZE bytes, so it "can't" fail */
97 83
 		return CL_EREAD;
98 84
 	}
85
+	pos += sizeof(uint32_t);
86
+
99 87
 	if(host32(i32) != TNEF_SIGNATURE) {
100
-		fclose(fp);
101 88
 		return CL_EFORMAT;
102 89
 	}
103 90
 
104
-	if(fread(&i16, sizeof(uint16_t), 1, fp) != 1) {
105
-		fclose(fp);
91
+	if(fmap_readn(*ctx->fmap, &i16, pos, sizeof(uint16_t)) != sizeof(uint16_t)) {
106 92
 		/* The file is at least MIN_SIZE bytes, so it "can't" fail */
107 93
 		return CL_EREAD;
108 94
 	}
95
+	pos += sizeof(uint16_t);
109 96
 
110 97
 	fb = NULL;
111 98
 	ret = CL_CLEAN;	/* we don't know if it's clean or not :-) */
... ...
@@ -116,12 +103,8 @@ cli_tnef(const char *dir, int desc, cli_ctx *ctx)
116 116
 		uint16_t type = 0, tag = 0;
117 117
 		int32_t length = 0;
118 118
 
119
-		switch(tnef_header(fp, &part, &type, &tag, &length)) {
119
+		switch(tnef_header(*ctx->fmap, &pos, &part, &type, &tag, &length)) {
120 120
 			case 0:
121
-				if(ferror(fp)) {
122
-					perror("read");
123
-					ret = CL_EREAD;
124
-				}
125 121
 				alldone = 1;
126 122
 				break;
127 123
 			case 1:
... ...
@@ -153,7 +136,7 @@ cli_tnef(const char *dir, int desc, cli_ctx *ctx)
153 153
 					fb = NULL;
154 154
 				}
155 155
 				fb = fileblobCreate();
156
-				if(tnef_message(fp, type, tag, length, fsize) != 0) {
156
+				if(tnef_message(*ctx->fmap, &pos, type, tag, length, fsize) != 0) {
157 157
 					cli_dbgmsg("TNEF: Error reading TNEF message\n");
158 158
 					ret = CL_EFORMAT;
159 159
 					alldone = 1;
... ...
@@ -161,7 +144,7 @@ cli_tnef(const char *dir, int desc, cli_ctx *ctx)
161 161
 				break;
162 162
 			case LVL_ATTACHMENT:
163 163
 				cli_dbgmsg("TNEF - found attachment\n");
164
-				if(tnef_attachment(fp, type, tag, length, dir, &fb, fsize) != 0) {
164
+				if(tnef_attachment(*ctx->fmap, &pos, type, tag, length, dir, &fb, fsize) != 0) {
165 165
 					cli_dbgmsg("TNEF: Error reading TNEF attachment\n");
166 166
 					ret = CL_EFORMAT;
167 167
 					alldone = 1;
... ...
@@ -189,9 +172,11 @@ cli_tnef(const char *dir, int desc, cli_ctx *ctx)
189 189
 
190 190
 						cli_warnmsg("Saving dump to %s:  refer to http://www.clamav.net/bugs\n", filename);
191 191
 
192
-						lseek(desc, 0L, SEEK_SET);
193
-						while((count = cli_readn(desc, buffer, sizeof(buffer))) > 0)
192
+						pos = 0;
193
+						while ((count = fmap_readn(*ctx->fmap, buffer, pos, sizeof(buffer))) > 0) {
194
+						        pos += count;
194 195
 							cli_writen(fout, buffer, count);
196
+						}
195 197
 						close(fout);
196 198
 					}
197 199
 					free(filename);
... ...
@@ -202,8 +187,6 @@ cli_tnef(const char *dir, int desc, cli_ctx *ctx)
202 202
 		}
203 203
 	} while(!alldone);
204 204
 
205
-	fclose(fp);
206
-
207 205
 	if(fb) {
208 206
 		cli_dbgmsg("cli_tnef: flushing final data\n");
209 207
 		if(fileblobGetFilename(fb) == NULL) {
... ...
@@ -219,7 +202,7 @@ cli_tnef(const char *dir, int desc, cli_ctx *ctx)
219 219
 }
220 220
 
221 221
 static int
222
-tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length, off_t fsize)
222
+tnef_message(fmap_t *map, off_t *pos, uint16_t type, uint16_t tag, int32_t length, off_t fsize)
223 223
 {
224 224
 	uint16_t i16;
225 225
 	off_t offset;
... ...
@@ -231,7 +214,7 @@ tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length, off_t fsize)
231 231
 	cli_dbgmsg("message tag 0x%x, type 0x%x, length %d\n", tag, type,
232 232
 		(int)length);
233 233
 
234
-	offset = ftell(fp);
234
+	offset = *pos;
235 235
 
236 236
 	/*
237 237
 	 * a lot of this stuff should be only discovered in debug mode...
... ...
@@ -243,16 +226,18 @@ tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length, off_t fsize)
243 243
 #ifdef	CL_DEBUG
244 244
 		case attTNEFVERSION:
245 245
 			/*assert(length == sizeof(uint32_t))*/
246
-			if(fread(&i32, sizeof(uint32_t), 1, fp) != 1)
246
+			if(fmap_readn(map, &i32, *pos, sizeof(uint32_t)) != sizeof(uint32_t))
247 247
 				return -1;
248
+			(*pos) += sizeof(uint32_t);
248 249
 			i32 = host32(i32);
249 250
 			cli_dbgmsg("TNEF version %d\n", i32);
250 251
 			break;
251 252
 		case attOEMCODEPAGE:
252 253
 			/* 8 bytes, but just print the first 4 */
253 254
 			/*assert(length == sizeof(uint32_t))*/
254
-			if(fread(&i32, sizeof(uint32_t), 1, fp) != 1)
255
+			if(fmap_readn(map, &i32, *pos, sizeof(uint32_t)) != sizeof(uint32_t))
255 256
 				return -1;
257
+			(*pos) += sizeof(uint32_t);
256 258
 			i32 = host32(i32);
257 259
 			cli_dbgmsg("TNEF codepage %d\n", i32);
258 260
 			break;
... ...
@@ -265,10 +250,11 @@ tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length, off_t fsize)
265 265
 			string = cli_malloc(length + 1);
266 266
 			if(string == NULL)
267 267
 				return -1;
268
-			if(fread(string, 1, (uint32_t)length, fp) != (uint32_t)length) {
268
+			if(fmap_readn(map, string, *pos, (uint32_t)length) != (uint32_t)length) {
269 269
 				free(string);
270 270
 				return -1;
271 271
 			}
272
+			(*pos) += (uint32_t)length;
272 273
 			string[length] = '\0';
273 274
 			cli_dbgmsg("TNEF class %s\n", string);
274 275
 			free(string);
... ...
@@ -285,18 +271,16 @@ tnef_message(FILE *fp, uint16_t type, uint16_t tag, int32_t length, off_t fsize)
285 285
 		cli_dbgmsg("TNEF: Incorrect length field in tnef_message\n");
286 286
 		return -1;
287 287
 	}
288
-	if(fseek(fp, offset + length, SEEK_SET) < 0)
289
-		return -1;
288
+	(*pos) = offset + length;
290 289
 
291 290
 	/* Checksum - TODO, verify */
292
-	if(fread(&i16, sizeof(uint16_t), 1, fp) != 1)
293
-		return -1;
291
+	(*pos) += 2;
294 292
 
295 293
 	return 0;
296 294
 }
297 295
 
298 296
 static int
299
-tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const char *dir, fileblob **fbref, off_t fsize)
297
+tnef_attachment(fmap_t *map, off_t *pos, uint16_t type, uint16_t tag, int32_t length, const char *dir, fileblob **fbref, off_t fsize)
300 298
 {
301 299
 	uint32_t todo;
302 300
 	uint16_t i16;
... ...
@@ -306,7 +290,7 @@ tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const cha
306 306
 	cli_dbgmsg("attachment tag 0x%x, type 0x%x, length %d\n", tag, type,
307 307
 		(int)length);
308 308
 
309
-	offset = ftell(fp);
309
+	offset = *pos;
310 310
 
311 311
 	switch(tag) {
312 312
 		case attATTACHTITLE:
... ...
@@ -315,10 +299,11 @@ tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const cha
315 315
 			string = cli_malloc(length + 1);
316 316
 			if(string == NULL)
317 317
 				return -1;
318
-			if(fread(string, 1, (uint32_t)length, fp) != (uint32_t)length) {
318
+			if(fmap_readn(map, string, *pos, (uint32_t)length) != (uint32_t)length) {
319 319
 				free(string);
320 320
 				return -1;
321 321
 			}
322
+			(*pos) += (uint32_t)length;
322 323
 			string[length] = '\0';
323 324
 			cli_dbgmsg("TNEF filename %s\n", string);
324 325
 			if(*fbref == NULL) {
... ...
@@ -338,9 +323,12 @@ tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const cha
338 338
 					return -1;
339 339
 			}
340 340
 			todo = length;
341
-			while(todo && !feof(fp) && !ferror(fp)) {
341
+			while(todo) {
342 342
 			    unsigned char buf[BUFSIZ];
343
-			    uint32_t got = fread(buf, 1, MIN(sizeof(buf), todo), fp);
343
+			    int32_t got = fmap_readn(map, buf, *pos, MIN(sizeof(buf), todo));
344
+			    if (got <= 0)
345
+				break;
346
+			    (*pos) += got;
344 347
 
345 348
 			    fileblobAddData(*fbref, buf, got);
346 349
 			    todo -= got;
... ...
@@ -358,29 +346,29 @@ tnef_attachment(FILE *fp, uint16_t type, uint16_t tag, int32_t length, const cha
358 358
 		cli_dbgmsg("TNEF: Incorrect length field in tnef_attachment\n");
359 359
 		return -1;
360 360
 	}
361
-	if(fseek(fp, (long)(offset + length), SEEK_SET) < 0)	/* shouldn't be needed */
362
-		return -1;
361
+	(*pos) = (long)(offset + length);	/* shouldn't be needed */
363 362
 
364
-	/* Checksum - TODO, verify */
365
-	if(fread(&i16, sizeof(uint16_t), 1, fp) != 1)
366
-		return -1;
363
+	(*pos) += 2;
367 364
 
368 365
 	return 0;
369 366
 }
370 367
 
371 368
 static int
372
-tnef_header(FILE *fp, uint8_t *part, uint16_t *type, uint16_t *tag, int32_t *length)
369
+tnef_header(fmap_t *map, off_t *pos, uint8_t *part, uint16_t *type, uint16_t *tag, int32_t *length)
373 370
 {
374 371
 	uint32_t i32;
372
+	int rc;
375 373
 
376
-	if(fread(part, sizeof(uint8_t), 1, fp) != 1)
374
+	if (fmap_readn(map, part, *pos, 1) != 1)
377 375
 		return 0;
376
+	(*pos)++;
378 377
 
379 378
 	if(*part == (uint8_t)0)
380 379
 		return 0;
381 380
 
382
-	if(fread(&i32, sizeof(uint32_t), 1, fp) != 1) {
383
-		if(((*part == '\n') || (*part == '\r')) && feof(fp)) {
381
+	rc = fmap_readn(map, &i32, *pos, sizeof(uint32_t));
382
+	if (rc != sizeof(uint32_t)) {
383
+		if(((*part == '\n') || (*part == '\r')) && (rc == 0)) {
384 384
 			/*
385 385
 			 * trailing newline in the file, could be caused by
386 386
 			 * broken quoted-printable encoding in the source
... ...
@@ -391,13 +379,15 @@ tnef_header(FILE *fp, uint8_t *part, uint16_t *type, uint16_t *tag, int32_t *len
391 391
 		}
392 392
 		return -1;
393 393
 	}
394
+	(*pos) += sizeof(uint32_t);
394 395
 
395 396
 	i32 = host32(i32);
396 397
 	*tag = (uint16_t)(i32 & 0xFFFF);
397 398
 	*type = (uint16_t)((i32 & 0xFFFF0000) >> 16);
398 399
 
399
-	if(fread(&i32, sizeof(uint32_t), 1, fp) != 1)
400
+	if(fmap_readn(map, &i32, *pos, sizeof(uint32_t)) != sizeof(uint32_t))
400 401
 		return -1;
402
+	(*pos) += sizeof(uint32_t);
401 403
 	*length = (int32_t)host32(i32);
402 404
 
403 405
 	cli_dbgmsg("message tag 0x%x, type 0x%x, length %d\n",
... ...
@@ -23,6 +23,6 @@
23 23
 
24 24
 #include "others.h"
25 25
 
26
-int cli_tnef(const char *dir, int desc, cli_ctx *ctx);
26
+int cli_tnef(const char *dir, cli_ctx *ctx);
27 27
 
28 28
 #endif
... ...
@@ -141,7 +141,10 @@ typedef struct arj_file_hdr_tag {
141 141
 
142 142
 typedef struct arj_decode_tag {
143 143
 	unsigned char *text;
144
-	int fd;
144
+	fmap_t *map;
145
+	size_t offset;
146
+	const uint8_t *buf;
147
+	const void *bufend;
145 148
 	uint16_t blocksize;
146 149
 	uint16_t bit_buf;
147 150
 	int bit_count;
... ...
@@ -164,13 +167,20 @@ static int fill_buf(arj_decode_t *decode_data, int n)
164 164
 		decode_data->bit_buf |= decode_data->sub_bit_buf << (n -= decode_data->bit_count);
165 165
 		if (decode_data->comp_size != 0) {
166 166
 			decode_data->comp_size--;
167
-			if (cli_readn(decode_data->fd, &decode_data->sub_bit_buf, 1) != 1) {
167
+			if (decode_data->buf == decode_data->bufend) {
168
+			    size_t len;
169
+			    decode_data->buf = fmap_need_off_once_len(decode_data->map, decode_data->offset, 8192, &len);
170
+			    if (!decode_data->buf || !len) {
168 171
 				/* the file is most likely corrupted, so
169 172
 				 * we return CL_EFORMAT instead of CL_EREAD
170 173
 				 */
171 174
 				decode_data->status = CL_EFORMAT;
172 175
 				return CL_EFORMAT;
176
+			    }
177
+			    decode_data->bufend = decode_data->buf + len;
173 178
 			}
179
+			decode_data->sub_bit_buf = *decode_data->buf++;
180
+			decode_data->offset++;
174 181
 		} else {
175 182
 			decode_data->sub_bit_buf = 0;
176 183
 		}
... ...
@@ -529,7 +539,7 @@ static uint16_t decode_p(arj_decode_t *decode_data)
529 529
 	return j;
530 530
 }
531 531
 
532
-static int decode(int fd, arj_metadata_t *metadata)
532
+static int decode(arj_metadata_t *metadata)
533 533
 {
534 534
 	int ret;
535 535
 
... ...
@@ -542,11 +552,13 @@ static int decode(int fd, arj_metadata_t *metadata)
542 542
 	if (!decode_data.text) {
543 543
 		return CL_EMEM;
544 544
 	}
545
-	decode_data.fd = fd;
545
+	decode_data.map = metadata->map;
546
+	decode_data.offset = metadata->offset;
546 547
 	decode_data.comp_size = metadata->comp_size;
547 548
 	ret = decode_start(&decode_data);
548 549
 	if (ret != CL_SUCCESS) {
549 550
 		free(decode_data.text);
551
+		metadata->offset = decode_data.offset;
550 552
 		return ret;
551 553
 	}
552 554
 	decode_data.status = CL_SUCCESS;
... ...
@@ -559,6 +571,7 @@ static int decode(int fd, arj_metadata_t *metadata)
559 559
 				out_ptr = 0;
560 560
 				if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
561 561
 					free(decode_data.text);
562
+					metadata->offset = decode_data.offset;
562 563
 					return CL_EWRITE;
563 564
 				}
564 565
 			}
... ...
@@ -584,6 +597,7 @@ static int decode(int fd, arj_metadata_t *metadata)
584 584
 						out_ptr = 0;
585 585
 						if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
586 586
 							free(decode_data.text);
587
+							metadata->offset = decode_data.offset;
587 588
 							return CL_EWRITE;
588 589
 						}
589 590
 					}
... ...
@@ -595,14 +609,16 @@ static int decode(int fd, arj_metadata_t *metadata)
595 595
 		}
596 596
 		if (decode_data.status != CL_SUCCESS) {
597 597
 			free(decode_data.text);
598
+			metadata->offset = decode_data.offset;
598 599
 			return decode_data.status;
599 600
 		}
600 601
 	}
601 602
 	if (out_ptr != 0) {
602 603
 		write_text(metadata->ofd, decode_data.text, out_ptr);
603 604
 	}
604
-	
605
+
605 606
 	free(decode_data.text);
607
+	metadata->offset = decode_data.offset;
606 608
 	return CL_SUCCESS;
607 609
 }
608 610
 
... ...
@@ -653,7 +669,7 @@ static uint16_t decode_len(arj_decode_t *decode_data)
653 653
 	return c;
654 654
 }
655 655
 
656
-static int decode_f(int fd, arj_metadata_t *metadata)
656
+static int decode_f(arj_metadata_t *metadata)
657 657
 {
658 658
 	int ret;
659 659
 
... ...
@@ -667,25 +683,29 @@ static int decode_f(int fd, arj_metadata_t *metadata)
667 667
 	if (!decode_data.text) {
668 668
 		return CL_EMEM;
669 669
 	}
670
-	decode_data.fd = fd;
670
+	decode_data.map = metadata->map;
671
+	decode_data.offset = metadata->offset;
671 672
 	decode_data.comp_size = metadata->comp_size;
672 673
 	ret = init_getbits(&decode_data);
673 674
 	if (ret != CL_SUCCESS) {
675
+	        metadata->offset = decode_data.offset;
674 676
 		return ret;
675 677
 	}
676
-    	decode_data.getlen = decode_data.getbuf = 0;
678
+	decode_data.getlen = decode_data.getbuf = 0;
677 679
 	decode_data.status = CL_SUCCESS;
678
-	
680
+
679 681
 	while (count < metadata->orig_size) {
680 682
 		chr = decode_len(&decode_data);
681 683
 		if (decode_data.status != CL_SUCCESS) {
682 684
 			free(decode_data.text);
685
+			metadata->offset = decode_data.offset;
683 686
 			return decode_data.status;
684
-		}		
687
+		}
685 688
 		if (chr == 0) {
686 689
 			ARJ_GETBITS(dd, chr, CHAR_BIT);
687 690
 			if (decode_data.status != CL_SUCCESS) {
688 691
 				free(decode_data.text);
692
+				metadata->offset = decode_data.offset;
689 693
 				return decode_data.status;
690 694
 			}
691 695
 			decode_data.text[out_ptr] = (unsigned char) chr;
... ...
@@ -694,6 +714,7 @@ static int decode_f(int fd, arj_metadata_t *metadata)
694 694
 				out_ptr = 0;
695 695
 				if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
696 696
 					free(decode_data.text);
697
+					metadata->offset = decode_data.offset;
697 698
 					return CL_EWRITE;
698 699
 				}
699 700
 			}
... ...
@@ -703,6 +724,7 @@ static int decode_f(int fd, arj_metadata_t *metadata)
703 703
 			pos = decode_ptr(&decode_data);
704 704
 			if (decode_data.status != CL_SUCCESS) {
705 705
 				free(decode_data.text);
706
+				metadata->offset = decode_data.offset;
706 707
 				return decode_data.status;
707 708
 			}
708 709
 			if ((i = out_ptr - pos - 1) < 0) {
... ...
@@ -718,6 +740,7 @@ static int decode_f(int fd, arj_metadata_t *metadata)
718 718
 					out_ptr = 0;
719 719
 					if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
720 720
 						free(decode_data.text);
721
+						metadata->offset = decode_data.offset;
721 722
 						return CL_EWRITE;
722 723
 					}
723 724
 				}
... ...
@@ -730,26 +753,28 @@ static int decode_f(int fd, arj_metadata_t *metadata)
730 730
 	if (out_ptr != 0) {
731 731
 		write_text(metadata->ofd, decode_data.text, out_ptr);
732 732
 	}
733
-	
733
+
734 734
 	free(decode_data.text);
735
+	metadata->offset = decode_data.offset;
735 736
 	return CL_SUCCESS;
736
-}	
737
+}
737 738
 
738
-static uint32_t arj_unstore(int ifd, int ofd, uint32_t len)
739
+static uint32_t arj_unstore(arj_metadata_t *metadata, int ofd, uint32_t len)
739 740
 {
740
-	unsigned char data[8192];
741
-	uint32_t count, rem;
741
+	const unsigned char *data;
742
+	uint32_t rem;
742 743
 	unsigned int todo;
744
+	size_t count;
743 745
 
744 746
 	cli_dbgmsg("in arj_unstore\n");
745 747
 	rem = len;
746 748
 
747 749
 	while (rem > 0) {
748 750
 		todo = (unsigned int) MIN(8192, rem);
749
-		count = cli_readn(ifd, data, todo);
750
-		if (count != todo) {
751
-			return len-rem;
752
-		}
751
+		data = fmap_need_off_once_len(metadata->map, metadata->offset, todo, &count);
752
+		if (!data)
753
+		    return len - rem;
754
+		metadata->offset += count;
753 755
 		if (cli_writen(ofd, data, count) != count) {
754 756
 			return len-rem-count;
755 757
 		}
... ...
@@ -758,14 +783,15 @@ static uint32_t arj_unstore(int ifd, int ofd, uint32_t len)
758 758
 	return len;
759 759
 }
760 760
 
761
-static int is_arj_archive(int fd)
761
+static int is_arj_archive(arj_metadata_t *metadata)
762 762
 {
763 763
 	const char header_id[2] = {0x60, 0xea};
764
-	char mark[2];
765
-	
766
-	if (cli_readn(fd, &mark[0], 2) != 2) {
767
-		return FALSE;
768
-	}
764
+	const char *mark;
765
+
766
+	mark = fmap_need_off_once(metadata->map, metadata->offset, 2);
767
+	if (!mark)
768
+	    return FALSE;
769
+	metadata->offset += 2;
769 770
 	if (memcmp(&mark[0], &header_id[0], 2) == 0) {
770 771
 		return TRUE;
771 772
 	}
... ...
@@ -773,18 +799,19 @@ static int is_arj_archive(int fd)
773 773
 	return FALSE;
774 774
 }
775 775
 
776
-static int arj_read_main_header(int fd)
776
+static int arj_read_main_header(arj_metadata_t *metadata)
777 777
 {
778 778
 	uint16_t header_size, count;
779 779
 	uint32_t crc;
780 780
 	arj_main_hdr_t main_hdr;
781
-	char *filename, *comment;
781
+	const char *filename, *comment;
782 782
 	off_t header_offset;
783 783
 
784
-	if (cli_readn(fd, &header_size, 2) != 2) {
785
-		return FALSE;
786
-	}
787
-	header_offset = lseek(fd, 0, SEEK_CUR);
784
+	if (fmap_readn(metadata->map, &header_size, metadata->offset, 2) != 2)
785
+	    return FALSE;
786
+
787
+	metadata->offset += 2;
788
+	header_offset = metadata->offset;
788 789
 	header_size = le16_to_host(header_size);
789 790
 	cli_dbgmsg("Header Size: %d\n", header_size);
790 791
 	if (header_size == 0) {
... ...
@@ -795,11 +822,10 @@ static int arj_read_main_header(int fd)
795 795
 		cli_dbgmsg("arj_read_header: invalid header_size: %u\n ", header_size);
796 796
 		return FALSE;
797 797
 	}
798
-	
799
-	if (cli_readn(fd, &main_hdr, 30) != 30) {
800
-		return FALSE;
801
-	}
802
-	
798
+	if (fmap_readn(metadata->map, &main_hdr, metadata->offset, 30) != 30)
799
+	    return FALSE;
800
+	metadata->offset += 30;
801
+
803 802
 	cli_dbgmsg("ARJ Main File Header\n");
804 803
 	cli_dbgmsg("First Header Size: %d\n", main_hdr.first_hdr_size);
805 804
 	cli_dbgmsg("Version: %d\n", main_hdr.version);
... ...
@@ -814,86 +840,50 @@ static int arj_read_main_header(int fd)
814 814
 		return FALSE;
815 815
 	}
816 816
 	if (main_hdr.first_hdr_size > 30) {
817
-		if (lseek(fd, main_hdr.first_hdr_size - 30, SEEK_CUR) == -1) {
818
-			return FALSE;
819
-		}
817
+	    metadata->offset += main_hdr.first_hdr_size - 30;
820 818
 	}
821 819
 
822
-	filename = (char *) cli_malloc(header_size);
823
-	if (!filename) {
824
-		return FALSE;
825
-	}
826
-	for (count=0 ; count < header_size ; count++) {
827
-		if (cli_readn(fd, &filename[count], 1) != 1) {
828
-			free(filename);
829
-			return FALSE;
830
-		}
831
-		if (filename[count] == '\0') {
832
-			break;
833
-		}
834
-	}
835
-	if (count == header_size) {
836
-		free(filename);
837
-		return FALSE;
838
-	}
839
-	comment = (char *) cli_malloc(header_size);
840
-	if (!comment) {
841
-		free(filename);
820
+	filename = fmap_need_offstr(metadata->map, metadata->offset, header_size);
821
+	if (!filename)
842 822
 		return FALSE;
843
-	}
844
-	for (count=0 ; count < header_size ; count++) {
845
-		if (cli_readn(fd, &comment[count], 1) != 1) {
846
-			free(filename);
847
-			free(comment);
848
-			return FALSE;
849
-		}
850
-		if (comment[count] == '\0') {
851
-			break;
852
-		}
853
-	}
854
-	if (count == header_size) {
855
-		free(filename);
856
-		free(comment);
823
+	metadata->offset += strlen(filename) + 1;
824
+
825
+	comment = fmap_need_offstr(metadata->map, metadata->offset, header_size);
826
+	if (!comment)
857 827
 		return FALSE;
858
-	}
828
+	metadata->offset += strlen(comment) + 1;
859 829
 	cli_dbgmsg("Filename: %s\n", filename);
860 830
 	cli_dbgmsg("Comment: %s\n", comment);
861
-	
862
-	free(filename);
863
-	free(comment);
864
-	
865
-	if (cli_readn(fd, &crc, 4) != 4) {
866
-		return FALSE;
867
-	}
868
-	
831
+
832
+	metadata->offset += 4; /* crc */
869 833
 	/* Skip past any extended header data */
870 834
 	for (;;) {
871
-		if (cli_readn(fd, &count, 2) != 2) {
835
+	        const uint16_t *countp = fmap_need_off_once(metadata->map, metadata->offset, 2);
836
+		if (!countp)
872 837
 			return FALSE;
873
-		}
874
-		count = le16_to_host(count);
838
+		count = cli_readint16(countp);
839
+		metadata->offset += 2;
875 840
 		cli_dbgmsg("Extended header size: %d\n", count);
876 841
 		if (count == 0) {
877 842
 			break;
878 843
 		}
879 844
 		/* Skip extended header + 4byte CRC */
880
-		if (lseek(fd, (off_t) (count + 4), SEEK_CUR) == -1) {
881
-			return FALSE;
882
-		}
845
+		metadata->offset += count + 4;
883 846
 	}
884 847
 	return TRUE;
885 848
 }
886 849
 
887
-static int arj_read_file_header(int fd, arj_metadata_t *metadata)
850
+static int arj_read_file_header(arj_metadata_t *metadata)
888 851
 {
889 852
 	uint16_t header_size, count;
890
-	char *filename, *comment;
853
+	const char *filename, *comment;
891 854
 	arj_file_hdr_t file_hdr;
892
-	
893
-	if (cli_readn(fd, &header_size, 2) != 2) {
894
-		return CL_EFORMAT;
895
-	}
855
+
856
+	if (fmap_readn(metadata->map, &header_size, metadata->offset, 2) != 2)
857
+	    return CL_EFORMAT;
896 858
 	header_size = le16_to_host(header_size);
859
+	metadata->offset += 2;
860
+
897 861
 	cli_dbgmsg("Header Size: %d\n", header_size);
898 862
 	if (header_size == 0) {
899 863
 		/* End of archive */
... ...
@@ -903,13 +893,14 @@ static int arj_read_file_header(int fd, arj_metadata_t *metadata)
903 903
 		cli_dbgmsg("arj_read_file_header: invalid header_size: %u\n ", header_size);
904 904
 		return CL_EFORMAT;
905 905
 	}
906
-	
907
-	if (cli_readn(fd, &file_hdr, 30) != 30) {
906
+
907
+	if (fmap_readn(metadata->map, &file_hdr, metadata->offset, 30) != 30) {
908 908
 		return CL_EFORMAT;
909 909
 	}
910
+	metadata->offset += 30;
910 911
 	file_hdr.comp_size = le32_to_host(file_hdr.comp_size);
911 912
 	file_hdr.orig_size = le32_to_host(file_hdr.orig_size);
912
-	
913
+
913 914
 	cli_dbgmsg("ARJ File Header\n");
914 915
 	cli_dbgmsg("First Header Size: %d\n", file_hdr.first_hdr_size);
915 916
 	cli_dbgmsg("Version: %d\n", file_hdr.version);
... ...
@@ -929,84 +920,42 @@ static int arj_read_file_header(int fd, arj_metadata_t *metadata)
929 929
 
930 930
 	/* Note: this skips past any extended file start position data (multi-volume) */
931 931
 	if (file_hdr.first_hdr_size > 30) {
932
-		if (lseek(fd, file_hdr.first_hdr_size - 30, SEEK_CUR) == -1) {
933
-			return CL_EFORMAT;
934
-		}
932
+	    metadata->offset += file_hdr.first_hdr_size - 30;
935 933
 	}
936 934
 
937
-	filename = (char *) cli_malloc(header_size);
938
-	if (!filename) {
939
-		return CL_EMEM;
940
-	}
941
-	for (count=0 ; count < header_size ; count++) {
942
-		if (cli_readn(fd, &filename[count], 1) != 1) {
943
-			free(filename);
944
-			return CL_EFORMAT;
945
-		}
946
-		if (filename[count] == '\0') {
947
-			break;
948
-		}
949
-	}
950
-	if (count == header_size) {
951
-		free(filename);
952
-		return CL_EFORMAT;
953
-	}
935
+	filename = fmap_need_offstr(metadata->map, metadata->offset, header_size);
936
+	if (!filename)
937
+		return FALSE;
938
+	metadata->offset += strlen(filename) + 1;
954 939
 
955
-	comment = (char *) cli_malloc(header_size);
956
-	if (!comment) {
957
-		free(filename);
958
-		return CL_EFORMAT;
959
-	}
960
-	for (count=0 ; count < header_size ; count++) {
961
-		if (cli_readn(fd, &comment[count], 1) != 1) {
962
-			free(filename);
963
-			free(comment);
964
-			return CL_EFORMAT;
965
-		}
966
-		if (comment[count] == '\0') {
967
-			break;
968
-		}
969
-	}
970
-	if (count == header_size) {
971
-		free(filename);
972
-		free(comment);
973
-		return CL_EFORMAT;
974
-	}
940
+	comment = fmap_need_offstr(metadata->map, metadata->offset, header_size);
941
+	if (!comment)
942
+		return FALSE;
943
+	metadata->offset += strlen(comment) + 1;
975 944
 	cli_dbgmsg("Filename: %s\n", filename);
976 945
 	cli_dbgmsg("Comment: %s\n", comment);
977 946
 	metadata->filename = cli_strdup(filename);
978 947
 
979
-	free(filename);
980
-	free(comment);
981
-
982 948
 	/* Skip CRC */
983
-	if (lseek(fd, (off_t) 4, SEEK_CUR) == -1) {
984
-		if(metadata->filename)
985
-		    free(metadata->filename);
986
-		metadata->filename = NULL;
987
-		return CL_EFORMAT;
988
-	}
989
-	
949
+	metadata->offset += 4;
950
+
990 951
 	/* Skip past any extended header data */
991 952
 	for (;;) {
992
-		if (cli_readn(fd, &count, 2) != 2) {
953
+	        const uint16_t *countp = fmap_need_off_once(metadata->map, metadata->offset, 2);
954
+		if (!countp) {
993 955
 			if(metadata->filename)
994 956
 			    free(metadata->filename);
995 957
 			metadata->filename = NULL;
996 958
 			return CL_EFORMAT;
997 959
 		}
998
-		count = le16_to_host(count);
960
+		count = cli_readint16(countp);
961
+		metadata->offset += 2;
999 962
 		cli_dbgmsg("Extended header size: %d\n", count);
1000 963
 		if (count == 0) {
1001 964
 			break;
1002 965
 		}
1003 966
 		/* Skip extended header + 4byte CRC */
1004
-		if (lseek(fd, (off_t) (count + 4), SEEK_CUR) == -1) {
1005
-			if(metadata->filename)
1006
-			    free(metadata->filename);
1007
-			metadata->filename = NULL;
1008
-			return CL_EFORMAT;
1009
-		}
967
+		metadata->offset += count + 4;
1010 968
 	}
1011 969
 	metadata->comp_size = file_hdr.comp_size;
1012 970
 	metadata->orig_size = file_hdr.orig_size;
... ...
@@ -1016,61 +965,58 @@ static int arj_read_file_header(int fd, arj_metadata_t *metadata)
1016 1016
 	if (!metadata->filename) {
1017 1017
 		return CL_EMEM;
1018 1018
 	}
1019
-	
1020
-	return CL_SUCCESS;
1019
+
1020
+        return CL_SUCCESS;
1021 1021
 }
1022 1022
 
1023
-int cli_unarj_open(int fd, const char *dirname)
1023
+int cli_unarj_open(fmap_t *map, const char *dirname, arj_metadata_t *metadata, size_t off)
1024 1024
 {
1025
-
1026 1025
 	cli_dbgmsg("in cli_unarj_open\n");
1027
-
1028
-	if (!is_arj_archive(fd)) {
1026
+	metadata->map = map;
1027
+	metadata->offset = off;
1028
+	if (!is_arj_archive(metadata)) {
1029 1029
 		cli_dbgmsg("Not in ARJ format\n");
1030 1030
 		return CL_EFORMAT;
1031 1031
 	}
1032
-	if (!arj_read_main_header(fd)) {
1032
+	if (!arj_read_main_header(metadata)) {
1033 1033
 		cli_dbgmsg("Failed to read main header\n");
1034 1034
 		return CL_EFORMAT;
1035 1035
 	}
1036 1036
 	return CL_SUCCESS;
1037 1037
 }
1038 1038
 
1039
-int cli_unarj_prepare_file(int fd, const char *dirname, arj_metadata_t *metadata)
1039
+int cli_unarj_prepare_file(const char *dirname, arj_metadata_t *metadata)
1040 1040
 {
1041 1041
 	cli_dbgmsg("in cli_unarj_prepare_file\n");
1042
-	if (!metadata || !dirname || (fd < 0)) {
1042
+	if (!metadata || !dirname) {
1043 1043
 		return CL_ENULLARG;
1044 1044
 	}
1045 1045
 	/* Each file is preceeded by the ARJ file marker */
1046
-	if (!is_arj_archive(fd)) {
1046
+	if (!is_arj_archive(metadata)) {
1047 1047
 		cli_dbgmsg("Not in ARJ format\n");
1048 1048
 		return CL_EFORMAT;
1049 1049
 	}
1050
-	return arj_read_file_header(fd, metadata);
1050
+	return arj_read_file_header(metadata);
1051 1051
 }
1052 1052
 
1053
-int cli_unarj_extract_file(int fd, const char *dirname, arj_metadata_t *metadata)
1053
+int cli_unarj_extract_file(const char *dirname, arj_metadata_t *metadata)
1054 1054
 {
1055 1055
 	off_t offset;
1056 1056
 	int ret = CL_SUCCESS;
1057 1057
 	char filename[1024];
1058
-	
1058
+
1059 1059
 	cli_dbgmsg("in cli_unarj_extract_file\n");
1060
-	if (!metadata || !dirname || (fd < 0)) {
1060
+	if (!metadata || !dirname) {
1061 1061
 		return CL_ENULLARG;
1062 1062
 	}
1063 1063
 
1064 1064
 	if (metadata->encrypted) {
1065 1065
 		cli_dbgmsg("PASSWORDed file (skipping)\n");
1066
-		offset = lseek(fd, 0, SEEK_CUR) + metadata->comp_size;
1067
-		cli_dbgmsg("Target offset: %lu\n", (unsigned long int) offset);
1068
-		if (lseek(fd, offset, SEEK_SET) != offset) {
1069
-			return CL_ESEEK;
1070
-		}
1066
+		metadata->offset += metadata->comp_size;
1067
+		cli_dbgmsg("Target offset: %lu\n", (unsigned long int) metadata->offset);
1071 1068
 		return CL_SUCCESS;
1072 1069
 	}
1073
-	
1070
+
1074 1071
 	snprintf(filename, 1024, "%s"PATHSEP"file.uar", dirname);
1075 1072
 	cli_dbgmsg("Filename: %s\n", filename);
1076 1073
 	metadata->ofd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
... ...
@@ -1079,7 +1025,7 @@ int cli_unarj_extract_file(int fd, const char *dirname, arj_metadata_t *metadata
1079 1079
 	}
1080 1080
 	switch (metadata->method) {
1081 1081
 		case 0:
1082
-			ret = arj_unstore(fd, metadata->ofd, metadata->comp_size);
1082
+			ret = arj_unstore(metadata, metadata->ofd, metadata->comp_size);
1083 1083
 			if (ret != metadata->comp_size) {
1084 1084
 				ret = CL_EWRITE;
1085 1085
 			} else {
... ...
@@ -1089,10 +1035,10 @@ int cli_unarj_extract_file(int fd, const char *dirname, arj_metadata_t *metadata
1089 1089
 		case 1:
1090 1090
 		case 2:
1091 1091
 		case 3:
1092
-			ret = decode(fd, metadata);
1092
+			ret = decode(metadata);
1093 1093
 			break;
1094 1094
 		case 4:
1095
-			ret = decode_f(fd, metadata);
1095
+			ret = decode_f(metadata);
1096 1096
 			break;
1097 1097
 		default:
1098 1098
 			ret = CL_EFORMAT;
... ...
@@ -23,6 +23,7 @@
23 23
 #ifndef __UNARJ_H
24 24
 #define __UNARJ_H
25 25
 
26
+#include "fmap.h"
26 27
 typedef struct arj_metadata_tag {
27 28
 	char *filename;
28 29
 	uint32_t comp_size;
... ...
@@ -30,10 +31,12 @@ typedef struct arj_metadata_tag {
30 30
 	int encrypted;
31 31
 	int ofd;
32 32
 	uint8_t method;
33
+	fmap_t *map;
34
+	size_t offset;
33 35
 } arj_metadata_t;
34 36
 
35
-int cli_unarj_open(int fd, const char *dirname);
36
-int cli_unarj_prepare_file(int fd, const char *dirname, arj_metadata_t *metadata);
37
-int cli_unarj_extract_file(int fd, const char *dirname, arj_metadata_t *metadata);
37
+int cli_unarj_open(fmap_t *map, const char *dirname, arj_metadata_t *metadata, size_t off);
38
+int cli_unarj_prepare_file(const char *dirname, arj_metadata_t *metadata);
39
+int cli_unarj_extract_file(const char *dirname, arj_metadata_t *metadata);
38 40
 
39 41
 #endif
... ...
@@ -57,28 +57,32 @@ octal(const char *str)
57 57
 }
58 58
 
59 59
 int
60
-cli_untar(const char *dir, int desc, unsigned int posix, cli_ctx *ctx)
60
+cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx)
61 61
 {
62 62
 	int size = 0, ret, fout=-1;
63 63
 	int in_block = 0;
64 64
 	unsigned int files = 0;
65 65
 	char fullname[NAME_MAX + 1];
66
+	size_t pos = 0;
66 67
 
67
-	cli_dbgmsg("In untar(%s, %d)\n", dir, desc);
68
+	cli_dbgmsg("In untar(%s)\n", dir);
68 69
 
69 70
 	for(;;) {
70
-		char block[BLOCKSIZE];
71
-		const int nread = cli_readn(desc, block, (unsigned int)sizeof(block));
71
+	        const char *block;
72
+		ssize_t nread;
72 73
 
73
-		if(!in_block && nread == 0)
74
+		block = fmap_need_off_once_len(*ctx->fmap, pos, BLOCKSIZE, &nread); 
75
+
76
+		if(!in_block && !nread)
74 77
 			break;
75 78
 
76
-		if(nread < 0) {
79
+		if(!block) {
77 80
 			if(fout>=0)
78 81
 				close(fout);
79 82
 			cli_errmsg("cli_untar: block read error\n");
80 83
 			return CL_EREAD;
81 84
 		}
85
+		pos += nread;
82 86
 
83 87
 		if(!in_block) {
84 88
 			char type;
... ...
@@ -169,13 +173,13 @@ cli_untar(const char *dir, int desc, unsigned int posix, cli_ctx *ctx)
169 169
 
170 170
 			if(skipEntry) {
171 171
 				const int nskip = (size % BLOCKSIZE || !size) ? size + BLOCKSIZE - (size % BLOCKSIZE) : size;
172
-				
172
+
173 173
 				if(nskip < 0) {
174 174
 					cli_dbgmsg("cli_untar: got nagative skip size, giving up\n");
175 175
 					return CL_CLEAN;
176 176
 				}
177 177
 				cli_dbgmsg("cli_untar: skipping entry\n");
178
-				lseek(desc, nskip, SEEK_CUR);
178
+				pos += nskip;
179 179
 				continue;
180 180
 			}
181 181
 
... ...
@@ -211,7 +215,7 @@ cli_untar(const char *dir, int desc, unsigned int posix, cli_ctx *ctx)
211 211
 		}
212 212
 		if (size == 0)
213 213
 			in_block = 0;
214
-        }	
214
+        }
215 215
 	if(fout>=0) {
216 216
 		lseek(fout, 0, SEEK_SET);
217 217
 		ret = cli_magic_scandesc(fout, ctx);
... ...
@@ -41,6 +41,6 @@
41 41
 
42 42
 #include "others.h"
43 43
 
44
-int cli_untar(const char *dir, int desc, unsigned int posix, cli_ctx *ctx);
44
+int cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx);
45 45
 
46 46
 #endif
... ...
@@ -118,6 +118,7 @@ const struct clam_option __clam_options[] = {
118 118
     { NULL, "vba", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
119 119
     { NULL, "vba-hex", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
120 120
     { NULL, "diff", 'd', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
121
+    { NULL, "compare", 'c', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
121 122
     { NULL, "run-cdiff", 'r', TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
122 123
     { NULL, "verify-cdiff", 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_SIGTOOL, "", "" },
123 124
     { NULL, "defaultcolors", 'd', TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMDTOP, "", "" },
... ...
@@ -73,7 +73,7 @@
73 73
 #include "libclamav/readdb.h"
74 74
 #include "libclamav/others.h"
75 75
 
76
-#define MAX_DEL_LOOKAHEAD   200
76
+#define MAX_DEL_LOOKAHEAD   5000
77 77
 
78 78
 static const struct dblist_s {
79 79
     const char *ext;
... ...
@@ -1781,6 +1781,15 @@ static int compare(const char *oldpath, const char *newpath, FILE *diff)
1781 1781
     return 0;
1782 1782
 }
1783 1783
 
1784
+static int compareone(const struct optstruct *opts)
1785
+{
1786
+    if(!opts->filename) {
1787
+	mprintf("!makediff: --compare requires two arguments\n");
1788
+	return -1;
1789
+    }
1790
+    return compare(optget(opts,"compare")->strarg, opts->filename[0], stdout);
1791
+}
1792
+
1784 1793
 static int dircopy(const char *src, const char *dest)
1785 1794
 {
1786 1795
 	DIR *dd;
... ...
@@ -2754,6 +2763,7 @@ static void help(void)
2754 2754
     mprintf("    --vba=FILE                             Extract VBA/Word6 macro code\n");
2755 2755
     mprintf("    --vba-hex=FILE                         Extract Word6 macro code with hex values\n");
2756 2756
     mprintf("    --diff=OLD NEW         -d OLD NEW      Create diff for OLD and NEW CVDs\n");
2757
+    mprintf("    --compare=OLD NEW      -c OLD NEW      Show diff between OLD and NEW files in cdiff format\n");
2757 2758
     mprintf("    --run-cdiff=FILE       -r FILE         Execute update script FILE in cwd\n");
2758 2759
     mprintf("    --verify-cdiff=DIFF CVD/CLD            Verify DIFF against CVD/CLD\n");
2759 2760
     mprintf("\n");
... ...
@@ -2837,6 +2847,8 @@ int main(int argc, char **argv)
2837 2837
 	ret = vbadump(opts);
2838 2838
     else if(optget(opts, "diff")->enabled)
2839 2839
 	ret = makediff(opts);
2840
+    else if(optget(opts, "compare")->enabled)
2841
+	ret = compareone(opts);
2840 2842
     else if(optget(opts, "run-cdiff")->enabled)
2841 2843
 	ret = rundiff(opts);
2842 2844
     else if(optget(opts, "verify-cdiff")->enabled) {
... ...
@@ -64,9 +64,9 @@ cli_ctx *convenience_ctx(int fd) {
64 64
     return ctx;
65 65
 }
66 66
 
67
-void destroy_ctx(cli_ctx *ctx) {
68
-    close((*(ctx->fmap))->fd);
67
+void destroy_ctx(int desc, cli_ctx *ctx) {
69 68
     funmap(*(ctx->fmap));
69
+    close(desc);
70 70
     free(ctx->fmap);
71 71
     cl_engine_free((struct cl_engine *)ctx->engine);
72 72
     free(ctx);
... ...
@@ -1042,7 +1042,7 @@ static int sigtool_scandir (const char *dirname, int hex_output)
1042 1042
 				}
1043 1043
 				if ((ret = cli_ole2_extract (dir, ctx, &vba))) {
1044 1044
 				    printf ("ERROR %s\n", cl_strerror (ret));
1045
-				    destroy_ctx(ctx);
1045
+				    destroy_ctx(desc, ctx);
1046 1046
 				    cli_rmdirs (dir);
1047 1047
 				    free (dir);
1048 1048
 				    closedir (dd);
... ...
@@ -1051,7 +1051,7 @@ static int sigtool_scandir (const char *dirname, int hex_output)
1051 1051
 
1052 1052
 				if(vba)
1053 1053
 				    sigtool_vba_scandir (dir, hex_output, vba);
1054
-				destroy_ctx(ctx);
1054
+				destroy_ctx(desc, ctx);
1055 1055
 				cli_rmdirs (dir);
1056 1056
 				free (dir);
1057 1057
 			    }
... ...
@@ -58,6 +58,7 @@ static void runtest(const char *file, uint64_t expected, int fail, int nojit,
58 58
     uint64_t v;
59 59
     struct cl_engine *engine;
60 60
     int fdin = -1;
61
+    char filestr[512];
61 62
 
62 63
     memset(&cctx, 0, sizeof(cctx));
63 64
     cctx.engine = engine = cl_engine_new();
... ...
@@ -103,7 +104,8 @@ static void runtest(const char *file, uint64_t expected, int fail, int nojit,
103 103
 
104 104
     ctx->ctx = &cctx;
105 105
     if (infile) {
106
-	fdin = open(infile, O_RDONLY);
106
+	snprintf(filestr, sizeof(filestr), OBJDIR"/%s", infile);
107
+	fdin = open(filestr, O_RDONLY);
107 108
 	if (fdin < 0 && errno == ENOENT)
108 109
 	    fdin = open_testfile(infile);
109 110
 	fail_unless(fdin >= 0, "failed to open infile");
... ...
@@ -11,6 +11,7 @@
11 11
 #include <check.h>
12 12
 #include <sys/types.h>
13 13
 #include <dirent.h>
14
+#include <sys/mman.h>
14 15
 #include "../libclamav/clamav.h"
15 16
 #include "../libclamav/others.h"
16 17
 #include "../libclamav/matcher.h"
... ...
@@ -336,12 +337,72 @@ static int get_test_file(int i, char *file, unsigned fsize, unsigned long *size)
336 336
     return fd;
337 337
 }
338 338
 
339
+static ssize_t pread_cb(void *handle, void *buf, size_t count, off_t offset)
340
+{
341
+    return pread(*((int*)handle), buf, count, offset);
342
+}
343
+
344
+START_TEST (test_cl_scanmap_callback_handle)
345
+{
346
+    const char *virname = NULL;
347
+    unsigned long int scanned = 0;
348
+    cl_fmap_t *map;
349
+    int ret;
350
+    char file[256];
351
+    unsigned long size;
352
+
353
+    int fd = get_test_file(_i, file, sizeof(file), &size);
354
+    /* intentionally use different way than scanners.c for testing */
355
+    map = cl_fmap_open_handle(&fd, 0, size, pread_cb, 1);
356
+    fail_unless(!!map, "cl_fmap_open_handle");
357
+
358
+    cli_dbgmsg("scanning (handle) %s\n", file);
359
+    ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
360
+    cli_dbgmsg("scan end (handle) %s\n", file);
361
+
362
+    fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret));
363
+    fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
364
+    close(fd);
365
+}
366
+END_TEST
367
+
368
+START_TEST (test_cl_scanmap_callback_mem)
369
+{
370
+    const char *virname = NULL;
371
+    unsigned long int scanned = 0;
372
+    cl_fmap_t *map;
373
+    int ret;
374
+    void *mem;
375
+    unsigned long size;
376
+    char file[256];
377
+
378
+    int fd = get_test_file(_i, file, sizeof(file), &size);
379
+
380
+    mem = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
381
+    fail_unless(mem != MAP_FAILED, "mmap");
382
+
383
+    /* intentionally use different way than scanners.c for testing */
384
+    map = cl_fmap_open_memory(mem, size);
385
+    fail_unless(!!map, "cl_fmap_open_mem");
386
+
387
+    cli_dbgmsg("scanning (mem) %s\n", file);
388
+    ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
389
+    cli_dbgmsg("scan end (mem) %s\n", file);
390
+    fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret));
391
+    fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s for %s", virname, file);
392
+    close(fd);
393
+    cl_fmap_close(map);
394
+
395
+    munmap(mem, size);
396
+}
397
+END_TEST
398
+
399
+
339 400
 static Suite *test_cl_suite(void)
340 401
 {
341 402
     Suite *s = suite_create("cl_api");
342 403
     TCase *tc_cl = tcase_create("cl_dup");
343 404
     TCase *tc_cl_scan = tcase_create("cl_scan");
344
-
345 405
     suite_add_tcase (s, tc_cl);
346 406
     tcase_add_test(tc_cl, test_cl_free);
347 407
     tcase_add_test(tc_cl, test_cl_dup);
... ...
@@ -368,8 +429,9 @@ static Suite *test_cl_suite(void)
368 368
     tcase_add_loop_test(tc_cl_scan, test_cl_scanfile, 0, expected_testfiles);
369 369
     tcase_add_loop_test(tc_cl_scan, test_cl_scandesc_callback, 0, expected_testfiles);
370 370
     tcase_add_loop_test(tc_cl_scan, test_cl_scanfile_callback, 0, expected_testfiles);
371
+    tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle, 0, expected_testfiles);
372
+    tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem, 0, expected_testfiles);
371 373
 #endif
372
-
373 374
     return s;
374 375
 }
375 376
 
... ...
@@ -723,5 +785,6 @@ int main(void)
723 723
     srunner_run_all(sr, CK_NORMAL);
724 724
     nf = srunner_ntests_failed(sr);
725 725
     srunner_free(sr);
726
+
726 727
     return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
727 728
 }
... ...
@@ -149,9 +149,13 @@ END_TEST
149 149
 START_TEST(test_screnc_nullterminate)
150 150
 {
151 151
 	int fd = open_testfile("input/screnc_test");
152
+	fmap_t *map;
152 153
 
153 154
 	fail_unless(mkdir(dir, 0700) == 0,"mkdir failed");
154
-	fail_unless(html_screnc_decode(fd, dir) == 1, "html_screnc_decode failed");
155
+	map = fmap(fd, 0, 0);
156
+	fail_unless(!!map, "fmap failed");
157
+	fail_unless(html_screnc_decode(map, dir) == 1, "html_screnc_decode failed");
158
+	funmap(map);
155 159
 	fail_unless(cli_rmdirs(dir) == 0, "rmdirs failed");
156 160
 	close(fd);
157 161
 }
... ...
@@ -208,6 +208,48 @@ START_TEST (test_base64)
208 208
     messageDestroy(m);
209 209
 }
210 210
 END_TEST
211
+
212
+static struct {
213
+    const char* u16;
214
+    const char* u8;
215
+} u16_tests[] = {
216
+    {"\x74\x00\x65\x00\x73\x00\x74\x00\x00\x00", "test"},
217
+    {"\xff\xfe\x00",""},
218
+    {"\x80\x00\x00","\xc2\x80"},
219
+    {"\xff\x07\x00","\xdf\xbf"},
220
+    {"\x00\x08\x00","\xe0\xa0\x80"},
221
+    {"\xff\x0f\x00","\xe0\xbf\xbf"},
222
+    {"\x00\x10\x00","\xe1\x80\x80"},
223
+    {"\xff\xcf\x00","\xec\xbf\xbf"},
224
+    {"\x00\xd0\x00","\xed\x80\x80"},
225
+    {"\xff\xd7\x00","\xed\x9f\xbf"},
226
+    {"\x00\xe0\x00","\xee\x80\x80"},
227
+    {"\xff\xff\x00","\xef\xbf\xbf"},
228
+    {"\x00\xd8\x00\xdc\x00","\xf0\x90\x80\x80"},
229
+    {"\xbf\xd8\xff\xdf\x00","\xf0\xbf\xbf\xbf"},
230
+    {"\xc0\xd8\x00\xdc\x00","\xf1\x80\x80\x80"},
231
+    {"\xbf\xdb\xff\xdf\x00","\xf3\xbf\xbf\xbf"},
232
+    {"\xc0\xdb\x00\xdc\x00","\xf4\x80\x80\x80"},
233
+    {"\xff\xdb\xff\xdf\x00","\xf4\x8f\xbf\xbf"},
234
+    {"\x00\xdc\x00\xd8\x00","\xef\xbf\xbd\xef\xbf\xbd"}
235
+};
236
+
237
+static unsigned u16_len(const char *s)
238
+{
239
+    unsigned i;
240
+    for (i=0;s[i] || s[i+1];i+=2) {}
241
+    return i;
242
+}
243
+
244
+START_TEST(test_u16_u8)
245
+{
246
+    char *result = cli_utf16_to_utf8(u16_tests[_i].u16, u16_len(u16_tests[_i].u16), UTF16_LE);
247
+    fail_unless(!!result, "cli_utf16_to_utf8 non-null");
248
+    fail_unless_fmt(!strcmp(result, u16_tests[_i].u8), "utf16_to_8 %d failed, expected: %s, got %s", _i, u16_tests[_i].u8, result);
249
+    free(result);
250
+}
251
+END_TEST
252
+
211 253
 #endif
212 254
 
213 255
 Suite *test_str_suite(void)
... ...
@@ -232,6 +274,9 @@ Suite *test_str_suite(void)
232 232
     tc_str = tcase_create("str functions");
233 233
     suite_add_tcase (s, tc_str);
234 234
     tcase_add_test(tc_str, hex2str);
235
+#ifdef CHECK_HAVE_LOOPS
236
+    tcase_add_loop_test(tc_str, test_u16_u8, 0, sizeof(u16_tests)/sizeof(u16_tests[0]));
237
+#endif
235 238
 
236 239
     tc_decodeline = tcase_create("decodeline");
237 240
     suite_add_tcase (s, tc_decodeline);
... ...
@@ -20,9 +20,6 @@
20 20
 /* name of the clamav user */
21 21
 #define CLAMAVUSER "clamav"
22 22
 
23
-/* enable clamuko */
24
-/* #undef CLAMUKO */
25
-
26 23
 /* enable debugging */
27 24
 /* #undef CL_DEBUG */
28 25
 
... ...
@@ -89,6 +86,9 @@
89 89
 /* "default FD_SETSIZE value" */
90 90
 #define DEFAULT_FD_SETSIZE 1024
91 91
 
92
+/* use fanotify */
93
+/* #undef FANOTIFY */
94
+
92 95
 /* whether _XOPEN_SOURCE needs to be defined for fd passing to work */
93 96
 /* #undef FDPASS_NEED_XOPEN */
94 97
 
... ...
@@ -508,7 +508,7 @@
508 508
 /* #undef USE_SYSLOG */
509 509
 
510 510
 /* Version number of package */
511
-#define VERSION "devel-clamav-0.97-233-g583cd65"
511
+#define VERSION "devel-clamav-0.97-253-g374be10"
512 512
 
513 513
 /* Version suffix for package */
514 514
 #define VERSION_SUFFIX ""
... ...
@@ -155,6 +155,7 @@
155 155
     <ResourceCompile Include="res\clamd.rc"/>
156 156
   </ItemGroup>
157 157
   <ItemGroup>
158
+    <ClCompile Include="..\clamd\fan.c"/>
158 159
     <ClCompile Include="..\clamd\clamd.c"/>
159 160
     <ClCompile Include="..\clamd\localserver.c"/>
160 161
     <ClCompile Include="..\clamd\others.c"/>
... ...
@@ -90,7 +90,6 @@ EXPORTS cli_bytecode_destroy @44225 NONAME
90 90
 EXPORTS cli_bytecode_context_destroy @44226 NONAME
91 91
 EXPORTS cli_bytecode_context_getresult_int @44227 NONAME
92 92
 EXPORTS cli_bytecode_run @44228 NONAME
93
-EXPORTS funmap @44229 NONAME
94 93
 EXPORTS cli_bytecode_context_setfile @44230 NONAME
95 94
 EXPORTS fmap @44231 NONAME
96 95
 EXPORTS cli_bytecode_context_setparam_int @44232 NONAME
... ...
@@ -166,6 +166,7 @@
166 166
     <ResourceCompile Include="res\libclamav.rc"/>
167 167
   </ItemGroup>
168 168
   <ItemGroup>
169
+    <ClCompile Include="..\libclamav\rijndael.c"/>
169 170
     <ClCompile Include="..\libclamav\iso9660.c"/>
170 171
     <ClCompile Include="..\libclamav\arc4.c"/>
171 172
     <ClCompile Include="..\libclamav\png.c"/>