Quellcode durchsuchen

7zip support, written by Dennis Schridde, and heavily Ryanified by me.

Ryan C. Gordon vor 20 Jahren
Ursprung
Commit
c527092aed
26 geänderte Dateien mit 3527 neuen und 61 gelöschten Zeilen
  1. 1 0
      CHANGELOG
  2. 9 2
      Makefile.am.newautomake
  3. 8 3
      archivers/Makefile.am
  4. 654 0
      archivers/lzma.c
  5. 14 0
      configure.in
  6. 29 0
      lzma/7zBuffer.c
  7. 19 0
      lzma/7zBuffer.h
  8. 76 0
      lzma/7zCrc.c
  9. 24 0
      lzma/7zCrc.h
  10. 147 0
      lzma/7zDecode.c
  11. 21 0
      lzma/7zDecode.h
  12. 5 0
      lzma/7zHeader.c
  13. 55 0
      lzma/7zHeader.h
  14. 1292 0
      lzma/7zIn.c
  15. 55 0
      lzma/7zIn.h
  16. 133 0
      lzma/7zItem.c
  17. 90 0
      lzma/7zItem.h
  18. 14 0
      lzma/7zMethodID.c
  19. 18 0
      lzma/7zMethodID.h
  20. 61 0
      lzma/7zTypes.h
  21. 97 0
      lzma/LZMA-LICENSE.txt
  22. 521 0
      lzma/LzmaStateDecode.c
  23. 109 0
      lzma/LzmaStateDecode.h
  24. 5 0
      lzma/Makefile.am
  25. 15 2
      physfs.c
  26. 55 54
      physfs_internal.h

+ 1 - 0
CHANGELOG

@@ -2,6 +2,7 @@
  * CHANGELOG.
  * CHANGELOG.
  */
  */
 
 
+04112006 - Added LZMA archiver...7zip support (thanks, Dennis!).
 03232006 - Added -fvisibility for gcc4 (http://gcc.gnu.org/wiki/Visibility)
 03232006 - Added -fvisibility for gcc4 (http://gcc.gnu.org/wiki/Visibility)
 01012006 - Cleaned up overflow checks in platform memory allocators (thanks to
 01012006 - Cleaned up overflow checks in platform memory allocators (thanks to
            Nicolas Lebedenco for pointing out the original issue with
            Nicolas Lebedenco for pointing out the original issue with

+ 9 - 2
Makefile.am.newautomake

@@ -105,7 +105,7 @@ EXTRA_DIST =	\
 
 
 else
 else
 
 
-SUBDIRS = platform archivers zlib123 . test extras
+SUBDIRS = platform archivers zlib123 lzma . test extras
 
 
 libphysfs_la_SOURCES =	\
 libphysfs_la_SOURCES =	\
 	physfs.c	\
 	physfs.c	\
@@ -118,13 +118,20 @@ else
 ZLIB_LIB =
 ZLIB_LIB =
 endif
 endif
 
 
+if BUILD_LZMA
+LZMA_LIB = lzma/liblzma.la
+else
+LZMA_LIB =
+endif
+
 libphysfs_la_LDFLAGS = 		\
 libphysfs_la_LDFLAGS = 		\
 	-release $(LT_RELEASE)	\
 	-release $(LT_RELEASE)	\
 	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 libphysfs_la_LIBADD =	\
 libphysfs_la_LIBADD =	\
 	archivers/libarchivers.la	\
 	archivers/libarchivers.la	\
 	platform/libplatform.la	\
 	platform/libplatform.la	\
-	$(ZLIB_LIB)
+	$(ZLIB_LIB) \
+	$(LZMA_LIB)
 
 
 EXTRA_DIST =	\
 EXTRA_DIST =	\
 	CREDITS \
 	CREDITS \

+ 8 - 3
archivers/Makefile.am

@@ -1,9 +1,13 @@
 noinst_LTLIBRARIES = libarchivers.la
 noinst_LTLIBRARIES = libarchivers.la
 
 
-if BUILD_ZLIB
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/zlib123
-else
 INCLUDES = -I$(top_srcdir)
 INCLUDES = -I$(top_srcdir)
+
+if BUILD_ZLIB
+INCLUDES += -I$(top_srcdir)/zlib123
+endif
+
+if BUILD_LZMA
+INCLUDES += -I$(top_srcdir)/lzma
 endif
 endif
 
 
 libarchivers_la_SOURCES =	\
 libarchivers_la_SOURCES =	\
@@ -13,5 +17,6 @@ libarchivers_la_SOURCES =	\
 	hog.c		\
 	hog.c		\
 	mvl.c		\
 	mvl.c		\
 	zip.c		\
 	zip.c		\
+	lzma.c		\
 	qpak.c		\
 	qpak.c		\
 	mix.c
 	mix.c

+ 654 - 0
archivers/lzma.c

@@ -0,0 +1,654 @@
+/*
+ * LZMA support routines for PhysicsFS.
+ *
+ * Please see the file LICENSE in the source's root directory.
+ *
+ *  This file written by Dennis Schridde, with some peeking at "7zMain.c"
+ *   by Igor Pavlov.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#if (defined PHYSFS_SUPPORTS_LZMA)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "physfs.h"
+
+#include "7zIn.h"
+#include "LzmaStateDecode.h"
+
+#define __PHYSICSFS_INTERNAL__
+#include "physfs_internal.h"
+
+#define LZMA_READBUFSIZE (16 * 1024)
+
+#define LZMA_7Z_FILE_SIG 0x7a37
+
+typedef struct
+{
+    ISzInStream InStream;
+    void *File;
+} CFileInStream;
+
+typedef struct
+{
+    CArchiveDatabaseEx db;
+    CFileInStream stream;
+    struct _LZMAentry *firstEntry;
+    struct _LZMAentry *lastEntry;
+} LZMAarchive;
+
+typedef struct _LZMAentry
+{
+    LZMAarchive *archive;
+    struct _LZMAentry *next;
+    struct _LZMAentry *previous;
+    CFileItem *file;
+    CLzmaDecoderState state;
+    PHYSFS_uint32 index;
+    PHYSFS_uint32 folderIndex;
+    PHYSFS_uint32 bufferedBytes;
+    PHYSFS_uint32 compressedSize;
+    PHYSFS_uint32 position;
+    PHYSFS_uint32 compressedPosition;
+    PHYSFS_uint8 buffer[LZMA_READBUFSIZE];
+    PHYSFS_uint8 *bufferPos;
+} LZMAentry;
+
+
+static void *SzAllocPhysicsFS(size_t size)
+{
+    return ((size == 0) ? NULL : allocator.Malloc(size));
+} /* SzAllocPhysicsFS */
+
+
+static void SzFreePhysicsFS(void *address)
+{
+    if (address != NULL)
+        allocator.Free(address);
+} /* SzFreePhysicsFS */
+
+
+SZ_RESULT SzFileReadImp(void *object, void *buffer,
+                        size_t size, size_t *processedSize)
+{
+    CFileInStream *s = (CFileInStream *) object;
+    size_t processedSizeLoc;
+
+    processedSizeLoc = __PHYSFS_platformRead(s->File, buffer, size, 1) * size;
+    if (processedSize != NULL)
+        *processedSize = processedSizeLoc;
+
+    return SZ_OK;
+} /* SzFileReadImp */
+
+
+SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
+{
+    CFileInStream *s = (CFileInStream *) object;
+    if (__PHYSFS_platformSeek(s->File, (PHYSFS_uint64) pos))
+        return SZ_OK;
+    return SZE_FAIL;
+} /* SzFileSeekImp */
+
+
+LZMAentry *lzma_find_entry(LZMAarchive *archive, const char *name)
+{
+    /* !!! FIXME: don't malloc here */
+    LZMAentry *entry = (LZMAentry *) allocator.Malloc(sizeof (LZMAentry));
+    const PHYSFS_uint32 imax = archive->db.Database.NumFiles;
+    for (entry->index = 0; entry->index < imax; entry->index++)
+    {
+        entry->file = archive->db.Database.Files + entry->index;
+        if (strcmp(entry->file->Name, name) == 0)
+            return entry;
+    } /* for */
+    allocator.Free(entry);
+
+    BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
+} /* lzma_find_entry */
+
+
+static PHYSFS_sint32 lzma_find_start_of_dir(LZMAarchive *archive,
+                                            const char *path,
+                                            int stop_on_first_find)
+{
+    PHYSFS_sint32 lo = 0;
+    PHYSFS_sint32 hi = (PHYSFS_sint32) (archive->db.Database.NumFiles - 1);
+    PHYSFS_sint32 middle;
+    PHYSFS_uint32 dlen = strlen(path);
+    PHYSFS_sint32 retval = -1;
+    const char *name;
+    int rc;
+
+    if (*path == '\0')  /* root dir? */
+        return(0);
+
+    if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */
+        dlen--;
+
+    while (lo <= hi)
+    {
+        middle = lo + ((hi - lo) / 2);
+        name = archive->db.Database.Files[middle].Name;
+        rc = strncmp(path, name, dlen);
+        if (rc == 0)
+        {
+            char ch = name[dlen];
+            if ('/' < ch) /* make sure this isn't just a substr match. */
+                rc = -1;
+            else if ('/' > ch)
+                rc = 1;
+            else
+            {
+                if (stop_on_first_find) /* Just checking dir's existance? */
+                    return(middle);
+
+                if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
+                    return(middle + 1);
+
+                /* there might be more entries earlier in the list. */
+                retval = middle;
+                hi = middle - 1;
+            } /* else */
+        } /* if */
+
+        if (rc > 0)
+            lo = middle + 1;
+        else
+            hi = middle - 1;
+    } /* while */
+
+    return(retval);
+} /* lzma_find_start_of_dir */
+
+
+/*
+ * Wrap all 7z calls in this, so the physfs error state is set appropriately.
+ */
+static int lzma_err(SZ_RESULT rc)
+{
+    switch (rc)
+    {
+        case SZ_OK: /* Same as LZMA_RESULT_OK */
+            break;
+        case SZE_DATA_ERROR: /* Same as LZMA_RESULT_DATA_ERROR */
+            __PHYSFS_setError(ERR_DATA_ERROR);
+            break;
+        case SZE_OUTOFMEMORY:
+            __PHYSFS_setError(ERR_OUT_OF_MEMORY);
+            break;
+        case SZE_CRC_ERROR:
+            __PHYSFS_setError(ERR_CORRUPTED);
+            break;
+        case SZE_NOTIMPL:
+            __PHYSFS_setError(ERR_NOT_IMPLEMENTED);
+            break;
+        case SZE_FAIL:
+            __PHYSFS_setError(ERR_UNKNOWN_ERROR);  /* !!! FIXME: right? */
+            break;
+        case SZE_ARCHIVE_ERROR:
+            __PHYSFS_setError(ERR_CORRUPTED);  /* !!! FIXME: right? */
+            break;
+        default:
+            __PHYSFS_setError(ERR_UNKNOWN_ERROR);
+    } /* switch */
+
+    return(rc);
+} /* lzma_err */
+
+
+static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+{
+    LZMAentry *entry = (LZMAentry *) opaque;
+
+    size_t wantBytes = objSize * objCount;
+    size_t decodedBytes = 0;
+    size_t totalDecodedBytes = 0;
+    size_t bufferBytes = 0;
+    size_t usedBufferedBytes = 0;
+    size_t availableBytes = entry->file->Size - entry->position;
+
+    BAIL_IF_MACRO(wantBytes == 0, NULL, 0); /* quick rejection. */
+
+    if (availableBytes < wantBytes)
+    {
+        wantBytes = availableBytes - (availableBytes % objSize);
+        objCount = wantBytes / objSize;
+        BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */
+        __PHYSFS_setError(ERR_PAST_EOF);   /* this is always true here. */
+    } /* if */
+
+    while (totalDecodedBytes < wantBytes)
+    {
+        if (entry->bufferedBytes == 0)
+        {
+            bufferBytes = entry->compressedSize - entry->compressedPosition;
+            if (bufferBytes > 0)
+            {
+                if (bufferBytes > LZMA_READBUFSIZE)
+                    bufferBytes = LZMA_READBUFSIZE;
+
+                entry->bufferedBytes =
+                        __PHYSFS_platformRead(entry->archive->stream.File,
+                                              entry->buffer, 1, bufferBytes);
+
+                if (entry->bufferedBytes <= 0)
+                    break;
+
+                entry->compressedPosition += entry->bufferedBytes;
+                entry->bufferPos = entry->buffer;
+            } /* if */
+        } /* if */
+
+        /* bufferedBytes == 0 if we finished decompressing */
+        lzma_err(LzmaDecode(&entry->state,
+            entry->bufferPos, entry->bufferedBytes, &usedBufferedBytes,
+            outBuffer, wantBytes, &decodedBytes,
+            (entry->bufferedBytes == 0)));
+
+        entry->bufferedBytes -= usedBufferedBytes;
+        entry->bufferPos += usedBufferedBytes;
+        totalDecodedBytes += decodedBytes;
+        entry->position += decodedBytes;
+    } /* while */
+
+    return(decodedBytes);
+} /* LZMA_read */
+
+
+static PHYSFS_sint64 LZMA_write(fvoid *opaque, const void *buf,
+                               PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
+} /* LZMA_write */
+
+
+static int LZMA_eof(fvoid *opaque)
+{
+    LZMAentry *entry = (LZMAentry *) opaque;
+    return (entry->compressedPosition >= entry->compressedSize);
+} /* LZMA_eof */
+
+
+static PHYSFS_sint64 LZMA_tell(fvoid *opaque)
+{
+    LZMAentry *entry = (LZMAentry *) opaque;
+    return (entry->position);
+} /* LZMA_tell */
+
+
+static int LZMA_seek(fvoid *opaque, PHYSFS_uint64 offset)
+{
+    LZMAentry *entry = (LZMAentry *) opaque;
+    PHYSFS_uint8 buf[512];
+    PHYSFS_uint32 maxread;
+
+    BAIL_IF_MACRO(offset < 0, ERR_SEEK_OUT_OF_RANGE, 0);
+    BAIL_IF_MACRO(offset > entry->file->Size, ERR_PAST_EOF, 0);
+
+    if (offset < entry->position)
+    {
+        __PHYSFS_platformSeek(entry->archive->stream.File,
+                              SzArDbGetFolderStreamPos(&entry->archive->db,
+                                                       entry->folderIndex, 0));
+        entry->position = 0;
+        entry->compressedPosition = 0;
+        LzmaDecoderInit(&entry->state);
+    } /* if */
+
+    while (offset != entry->position)
+    {
+        maxread = (PHYSFS_uint32) (offset - entry->position);
+        if (maxread > sizeof (buf))
+            maxread = sizeof (buf);
+        if (!LZMA_read(entry, buf, maxread, 1))
+            return(0);
+    } /* while */
+
+    return(1);
+} /* LZMA_seek */
+
+
+static PHYSFS_sint64 LZMA_fileLength(fvoid *opaque)
+{
+    return ((LZMAentry *) opaque)->file->Size;
+} /* LZMA_fileLength */
+
+
+static int LZMA_fileClose(fvoid *opaque)
+{
+    LZMAentry *entry = (LZMAentry *) opaque;
+
+    /* Fix archive */
+    if (entry == entry->archive->firstEntry)
+        entry->archive->firstEntry = entry->next;
+    if (entry == entry->archive->lastEntry)
+        entry->archive->lastEntry = entry->previous;
+
+    /* Fix neighbours */
+    if (entry->previous != NULL)
+        entry->previous->next = entry->next;
+    if (entry->next != NULL)
+        entry->next->previous = entry->previous;
+
+    /* Free */
+    if (entry->state.Probs != NULL)
+        allocator.Free(entry->state.Probs);
+    if (entry->state.Dictionary != NULL)
+        allocator.Free(entry->state.Dictionary);
+
+    allocator.Free(entry);
+    return(1);
+} /* LZMA_fileClose */
+
+
+static int LZMA_isArchive(const char *filename, int forWriting)
+{
+    PHYSFS_uint8 sig[k7zSignatureSize];
+    PHYSFS_uint8 res;
+    void *in;
+
+    BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
+
+    in = __PHYSFS_platformOpenRead(filename);
+    BAIL_IF_MACRO(in == NULL, NULL, 0);
+
+    if (__PHYSFS_platformRead(in, sig, k7zSignatureSize, 1) != 1)
+        BAIL_MACRO(NULL, 0);
+
+    res = TestSignatureCandidate(sig);
+    __PHYSFS_platformClose(in);
+
+    return res;
+} /* LZMA_isArchive */
+
+
+static void *LZMA_openArchive(const char *name, int forWriting)
+{
+    LZMAarchive *archive;
+    ISzAlloc allocImp;
+    ISzAlloc allocTempImp;
+
+    BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
+
+    archive = (LZMAarchive *) allocator.Malloc(sizeof(LZMAarchive));
+    if ((archive->stream.File = __PHYSFS_platformOpenRead(name)) == NULL)
+    {
+        allocator.Free(archive);
+        return NULL;
+    } /* if */
+
+    archive->stream.InStream.Read = SzFileReadImp;
+    archive->stream.InStream.Seek = SzFileSeekImp;
+
+    archive->firstEntry = NULL;
+    archive->lastEntry = NULL;
+
+    allocImp.Alloc = SzAllocPhysicsFS;
+    allocImp.Free = SzFreePhysicsFS;
+
+    allocTempImp.Alloc = SzAllocPhysicsFS;
+    allocTempImp.Free = SzFreePhysicsFS;
+
+    InitCrcTable();
+    SzArDbExInit(&archive->db);
+    if (lzma_err(SzArchiveOpen(&archive->stream.InStream, &archive->db,
+                               &allocImp, &allocTempImp)) != SZ_OK)
+    {
+        SzArDbExFree(&archive->db, allocImp.Free);
+        __PHYSFS_platformClose(archive->stream.File);
+        allocator.Free(archive);
+        return NULL;
+    } /* if */
+
+    return(archive);
+} /* LZMA_openArchive */
+
+
+/*
+ * Moved to seperate function so we can use alloca then immediately throw
+ *  away the allocated stack space...
+ */
+static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
+                           const char *odir, const char *str, PHYSFS_sint32 ln)
+{
+    char *newstr = alloca(ln + 1);
+    if (newstr == NULL)
+        return;
+
+    memcpy(newstr, str, ln);
+    newstr[ln] = '\0';
+    cb(callbackdata, odir, newstr);
+} /* doEnumCallback */
+
+
+static void LZMA_enumerateFiles(dvoid *opaque, const char *dname,
+                                int omitSymLinks, PHYSFS_EnumFilesCallback cb,
+                                const char *origdir, void *callbackdata)
+{
+    LZMAarchive *archive = (LZMAarchive *) opaque;
+    PHYSFS_sint32 dlen;
+    PHYSFS_sint32 dlen_inc;
+    PHYSFS_sint32 max;
+    PHYSFS_sint32 i;
+
+    i = lzma_find_start_of_dir(archive, dname, 0);
+    if (i == -1)  /* no such directory. */
+        return;
+
+    dlen = strlen(dname);
+    if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
+        dlen--;
+
+    dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
+    max = (PHYSFS_sint32) archive->db.Database.NumFiles;
+    while (i < max)
+    {
+        char *add;
+        char *ptr;
+        PHYSFS_sint32 ln;
+        char *e = archive->db.Database.Files[i].Name;
+        if ((dlen) && ((strncmp(e, dname, dlen)) || (e[dlen] != '/')))
+            break;  /* past end of this dir; we're done. */
+
+        add = e + dlen_inc;
+        ptr = strchr(add, '/');
+        ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
+        doEnumCallback(cb, callbackdata, origdir, add, ln);
+        ln += dlen_inc;  /* point past entry to children... */
+
+        /* increment counter and skip children of subdirs... */
+        while ((++i < max) && (ptr != NULL))
+        {
+            char *e_new = archive->db.Database.Files[i].Name;
+            if ((strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
+                break;
+        } /* while */
+    } /* while */
+} /* LZMA_enumerateFiles */
+
+
+static int LZMA_exists(dvoid *opaque, const char *name)
+{
+    return(lzma_find_entry((LZMAarchive *) opaque, name) != NULL);
+} /* LZMA_exists */
+
+
+static PHYSFS_sint64 LZMA_getLastModTime(dvoid *opaque,
+                                        const char *name,
+                                        int *fileExists)
+{
+    BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1); /* !!! FIXME: Implement this! */
+} /* LZMA_getLastModTime */
+
+
+static int LZMA_isDirectory(dvoid *opaque, const char *name, int *fileExists)
+{
+    LZMAentry *entry = lzma_find_entry((LZMAarchive *) opaque, name);
+    int isDir = entry->file->IsDirectory;
+
+    *fileExists = (entry != NULL);
+    allocator.Free(entry);
+
+    return(isDir);
+} /* LZMA_isDirectory */
+
+
+static int LZMA_isSymLink(dvoid *opaque, const char *name, int *fileExists)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* LZMA_isSymLink */
+
+
+static fvoid *LZMA_openRead(dvoid *opaque, const char *name, int *fileExists)
+{
+    LZMAarchive *archive = (LZMAarchive *) opaque;
+    LZMAentry *entry = lzma_find_entry(archive, name);
+    BAIL_IF_MACRO(entry == NULL, ERR_NO_SUCH_FILE, NULL);
+
+    entry->archive = archive;
+    entry->compressedPosition = 0;
+    entry->position = 0;
+    entry->folderIndex =
+            entry->archive->db.FileIndexToFolderIndexMap[entry->index];
+
+    entry->next = NULL;
+    entry->previous = entry->archive->lastEntry;
+    if (entry->previous != NULL)
+        entry->previous->next = entry;
+    entry->archive->lastEntry = entry;
+    if (entry->archive->firstEntry == NULL)
+        entry->archive->firstEntry = entry;
+
+    entry->bufferPos = entry->buffer;
+    entry->bufferedBytes = 0;
+    entry->compressedSize = SzArDbGetFolderFullPackSize(&entry->archive->db,
+                                                        entry->folderIndex);
+
+    __PHYSFS_platformSeek(entry->archive->stream.File,
+                          SzArDbGetFolderStreamPos(&entry->archive->db,
+                                                   entry->folderIndex, 0));
+
+    /* Create one CLzmaDecoderState per entry */
+    CFolder *folder = entry->archive->db.Database.Folders + entry->folderIndex;
+    CCoderInfo *coder = folder->Coders;
+
+    if ((folder->NumPackStreams != 1) || (folder->NumCoders != 1))
+    {
+        LZMA_fileClose(entry);
+        BAIL_MACRO(ERR_LZMA_NOTIMPL, NULL);
+    } /* if */
+
+    if (lzma_err(LzmaDecodeProperties(&entry->state.Properties, coder->Properties.Items, coder->Properties.Capacity)) != LZMA_RESULT_OK)
+        return NULL;
+
+    entry->state.Probs = (CProb *) allocator.Malloc(LzmaGetNumProbs(&entry->state.Properties) * sizeof(CProb));
+    if (entry->state.Probs == NULL)
+    {
+        LZMA_fileClose(entry);
+        BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
+    } /* if */
+
+	if (entry->state.Properties.DictionarySize == 0)
+		entry->state.Dictionary = NULL;
+	else
+	{
+		entry->state.Dictionary = (unsigned char *) allocator.Malloc(entry->state.Properties.DictionarySize);
+		if (entry->state.Dictionary == NULL)
+		{
+			LZMA_fileClose(entry);
+			BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
+		} /* if */
+	} /* else */
+	LzmaDecoderInit(&entry->state);
+
+	return(entry);
+} /* LZMA_openRead */
+
+
+static fvoid *LZMA_openWrite(dvoid *opaque, const char *filename)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* LZMA_openWrite */
+
+
+static fvoid *LZMA_openAppend(dvoid *opaque, const char *filename)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* LZMA_openAppend */
+
+
+static void LZMA_dirClose(dvoid *opaque)
+{
+	LZMAarchive *archive = (LZMAarchive *) opaque;
+	LZMAentry *entry = archive->firstEntry;
+
+	while (entry != NULL)
+	{
+		entry = entry->next;
+		LZMA_fileClose(entry->previous);
+	} /* while */
+
+	SzArDbExFree(&archive->db, SzFreePhysicsFS);
+	__PHYSFS_platformClose(archive->stream.File);
+    allocator.Free(archive);
+} /* LZMA_dirClose */
+
+
+static int LZMA_remove(dvoid *opaque, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* LZMA_remove */
+
+
+static int LZMA_mkdir(dvoid *opaque, const char *name)
+{
+    BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
+} /* LZMA_mkdir */
+
+
+const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_LZMA =
+{
+    "7Z",
+    LZMA_ARCHIVE_DESCRIPTION,
+    "Dennis Schridde <devurandom@gmx.net>",
+    "http://icculus.org/physfs/",
+};
+
+
+const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
+{
+    &__PHYSFS_ArchiveInfo_LZMA,
+    LZMA_isArchive,          /* isArchive() method      */
+    LZMA_openArchive,        /* openArchive() method    */
+    LZMA_enumerateFiles,     /* enumerateFiles() method */
+    LZMA_exists,             /* exists() method         */
+    LZMA_isDirectory,        /* isDirectory() method    */
+    LZMA_isSymLink,          /* isSymLink() method      */
+    LZMA_getLastModTime,     /* getLastModTime() method */
+    LZMA_openRead,           /* openRead() method       */
+    LZMA_openWrite,          /* openWrite() method      */
+    LZMA_openAppend,         /* openAppend() method     */
+    LZMA_remove,             /* remove() method         */
+    LZMA_mkdir,              /* mkdir() method          */
+    LZMA_dirClose,           /* dirClose() method       */
+    LZMA_read,               /* read() method           */
+    LZMA_write,              /* write() method          */
+    LZMA_eof,                /* eof() method            */
+    LZMA_tell,               /* tell() method           */
+    LZMA_seek,               /* seek() method           */
+    LZMA_fileLength,         /* fileLength() method     */
+    LZMA_fileClose           /* fileClose() method      */
+};
+
+#endif  /* defined PHYSFS_SUPPORTS_LZMA */
+
+/* end of lzma.c ... */
+

+ 14 - 0
configure.in

@@ -139,6 +139,18 @@ if test x$enable_zip = xyes; then
 fi
 fi
 
 
 
 
+require_lzma="no"
+ 
+dnl Check for lzma archiver inclusion...
+AC_ARG_ENABLE(lzma,
+[  --enable-lzma               enable lzma support [default=yes]],
+                , enable_lzma=yes)
+if test x$enable_lzma = xyes; then
+  AC_DEFINE([PHYSFS_SUPPORTS_LZMA], 1, [define if lzma support is enabled])
+  require_lzma="yes"
+fi
+
+
 dnl Check for grp archiver inclusion...
 dnl Check for grp archiver inclusion...
 AC_ARG_ENABLE(grp,
 AC_ARG_ENABLE(grp,
 [  --enable-grp               enable Build Engine GRP support [default=yes]],
 [  --enable-grp               enable Build Engine GRP support [default=yes]],
@@ -564,6 +576,7 @@ LDFLAGS="$LDFLAGS $PHYSFSLDFLAGS -no-undefined"
 
 
 dnl Add Makefile conditionals
 dnl Add Makefile conditionals
 AM_CONDITIONAL(BUILD_ZLIB, test x$enable_internal_zlib = xyes)
 AM_CONDITIONAL(BUILD_ZLIB, test x$enable_internal_zlib = xyes)
+AM_CONDITIONAL(BUILD_LZMA, test x$enable_lzma = xyes)
 AM_CONDITIONAL(BUILD_TEST_PHYSFS, test x$enable_testprog = xyes)
 AM_CONDITIONAL(BUILD_TEST_PHYSFS, test x$enable_testprog = xyes)
 AM_CONDITIONAL(BUILD_MACOSX, test x$this_is_macosx = xyes)
 AM_CONDITIONAL(BUILD_MACOSX, test x$this_is_macosx = xyes)
 AM_CONDITIONAL(BUILD_BEOS, test x$this_is_beos = xyes)
 AM_CONDITIONAL(BUILD_BEOS, test x$this_is_beos = xyes)
@@ -575,6 +588,7 @@ Makefile
 archivers/Makefile
 archivers/Makefile
 platform/Makefile
 platform/Makefile
 zlib123/Makefile
 zlib123/Makefile
+lzma/Makefile
 test/Makefile
 test/Makefile
 extras/Makefile
 extras/Makefile
 physfs.spec
 physfs.spec

+ 29 - 0
lzma/7zBuffer.c

@@ -0,0 +1,29 @@
+/* 7zBuffer.c */
+
+#include "7zBuffer.h"
+#include "7zAlloc.h"
+
+void SzByteBufferInit(CSzByteBuffer *buffer)
+{
+  buffer->Capacity = 0;
+  buffer->Items = 0;
+}
+
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
+{
+  buffer->Capacity = newCapacity;
+  if (newCapacity == 0)
+  {
+    buffer->Items = 0;
+    return 1;
+  }
+  buffer->Items = (Byte *)allocFunc(newCapacity);
+  return (buffer->Items != 0);
+}
+
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
+{
+  freeFunc(buffer->Items);
+  buffer->Items = 0;
+  buffer->Capacity = 0;
+}

+ 19 - 0
lzma/7zBuffer.h

@@ -0,0 +1,19 @@
+/* 7zBuffer.h */
+
+#ifndef __7Z_BUFFER_H
+#define __7Z_BUFFER_H
+
+#include <stddef.h>
+#include "7zTypes.h"
+
+typedef struct _CSzByteBuffer
+{    
+	size_t Capacity;
+  Byte *Items;
+}CSzByteBuffer;
+
+void SzByteBufferInit(CSzByteBuffer *buffer);
+int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size));
+void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *));
+
+#endif

+ 76 - 0
lzma/7zCrc.c

@@ -0,0 +1,76 @@
+/* 7zCrc.c */
+
+#include "7zCrc.h"
+
+#define kCrcPoly 0xEDB88320
+
+UInt32 g_CrcTable[256];
+
+void InitCrcTable()
+{
+  UInt32 i;
+  for (i = 0; i < 256; i++)
+  {
+    UInt32 r = i;
+    int j;
+    for (j = 0; j < 8; j++)
+      if (r & 1) 
+        r = (r >> 1) ^ kCrcPoly;
+      else     
+        r >>= 1;
+    g_CrcTable[i] = r;
+  }
+}
+
+void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; }
+UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; } 
+
+void CrcUpdateByte(UInt32 *crc, Byte b)
+{
+  *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8);
+}
+
+void CrcUpdateUInt16(UInt32 *crc, UInt16 v)
+{
+  CrcUpdateByte(crc, (Byte)v);
+  CrcUpdateByte(crc, (Byte)(v >> 8));
+}
+
+void CrcUpdateUInt32(UInt32 *crc, UInt32 v)
+{
+  int i;
+  for (i = 0; i < 4; i++)
+    CrcUpdateByte(crc, (Byte)(v >> (8 * i)));
+}
+
+void CrcUpdateUInt64(UInt32 *crc, UInt64 v)
+{
+  int i;
+  for (i = 0; i < 8; i++)
+  {
+    CrcUpdateByte(crc, (Byte)(v));
+    v >>= 8;
+  }
+}
+
+void CrcUpdate(UInt32 *crc, const void *data, size_t size)
+{
+  UInt32 v = *crc;
+  const Byte *p = (const Byte *)data;
+  for (; size > 0 ; size--, p++)
+    v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8);
+  *crc = v;
+}
+
+UInt32 CrcCalculateDigest(const void *data, size_t size)
+{
+  UInt32 crc;
+  CrcInit(&crc);
+  CrcUpdate(&crc, data, size);
+  return CrcGetDigest(&crc);
+}
+
+int CrcVerifyDigest(UInt32 digest, const void *data, size_t size)
+{
+  return (CrcCalculateDigest(data, size) == digest);
+}

+ 24 - 0
lzma/7zCrc.h

@@ -0,0 +1,24 @@
+/* 7zCrc.h */
+
+#ifndef __7Z_CRC_H
+#define __7Z_CRC_H
+
+#include <stddef.h>
+
+#include "7zTypes.h"
+
+extern UInt32 g_CrcTable[256];
+void InitCrcTable();
+
+void CrcInit(UInt32 *crc);
+UInt32 CrcGetDigest(UInt32 *crc);
+void CrcUpdateByte(UInt32 *crc, Byte v);
+void CrcUpdateUInt16(UInt32 *crc, UInt16 v);
+void CrcUpdateUInt32(UInt32 *crc, UInt32 v);
+void CrcUpdateUInt64(UInt32 *crc, UInt64 v);
+void CrcUpdate(UInt32 *crc, const void *data, size_t size);
+ 
+UInt32 CrcCalculateDigest(const void *data, size_t size);
+int CrcVerifyDigest(UInt32 digest, const void *data, size_t size);
+
+#endif

+ 147 - 0
lzma/7zDecode.c

@@ -0,0 +1,147 @@
+/* 7zDecode.c */
+
+#include "7zDecode.h"
+#include "LzmaStateDecode.h" // NOTE : Modified to use LzmaStateDecode(.c,.h) instead of LzmaDecode(.c,.h) and hardcoded _SZ_ONE_DIRECTORY behaviour
+
+CMethodID k_Copy = { { 0x0 }, 1 };
+CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+
+#ifdef _LZMA_IN_CB
+
+typedef struct _CLzmaInCallbackImp
+{
+  ILzmaInCallback InCallback;
+  ISzInStream *InStream;
+  size_t Size;
+} CLzmaInCallbackImp;
+
+int LzmaReadImp(void *object, const unsigned char **buffer, size_t *size)
+{
+  CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
+  size_t processedSize;
+  SZ_RESULT res;
+  *size = 0;
+  res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize);
+  *size = (size_t)processedSize;
+  if (processedSize > cb->Size)
+    return (int)SZE_FAIL;
+  cb->Size -= processedSize;
+  if (res == SZ_OK)
+    return 0;
+  return (int)res;
+}
+
+#endif
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *inStream,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize,
+    size_t *outSizeProcessed, ISzAlloc *allocMain)
+{
+  UInt32 si;
+  size_t inSize = 0;
+  CCoderInfo *coder;
+  if (folder->NumPackStreams != 1)
+    return SZE_NOTIMPL;
+  if (folder->NumCoders != 1)
+    return SZE_NOTIMPL;
+  coder = folder->Coders;
+  *outSizeProcessed = 0;
+
+  for (si = 0; si < folder->NumPackStreams; si++)
+    inSize += (size_t)packSizes[si];
+
+  if (AreMethodsEqual(&coder->MethodID, &k_Copy))
+  {
+    size_t i;
+    if (inSize != outSize)
+      return SZE_DATA_ERROR;
+    #ifdef _LZMA_IN_CB
+    for (i = 0; i < inSize;)
+    {
+      size_t j;
+      Byte *inBuffer;
+      size_t bufferSize;
+      RINOK(inStream->Read((void *)inStream,  (void **)&inBuffer, inSize - i, &bufferSize));
+      if (bufferSize == 0)
+        return SZE_DATA_ERROR;
+      if (bufferSize > inSize - i)
+        return SZE_FAIL;
+      *outSizeProcessed += bufferSize;
+      for (j = 0; j < bufferSize && i < inSize; j++, i++)
+        outBuffer[i] = inBuffer[j];
+    }
+    #else
+    for (i = 0; i < inSize; i++)
+      outBuffer[i] = inBuffer[i];
+    *outSizeProcessed = inSize;
+    #endif
+    return SZ_OK;
+  }
+
+  if (AreMethodsEqual(&coder->MethodID, &k_LZMA))
+  {
+    #ifdef _LZMA_IN_CB
+    CLzmaInCallbackImp lzmaCallback;
+    #else
+    size_t inProcessed;
+    #endif
+
+    CLzmaDecoderState state;  /* it's about 24-80 bytes structure, if int is 32-bit */
+    int result;
+    size_t outSizeProcessedLoc;
+
+    #ifdef _LZMA_IN_CB
+    lzmaCallback.Size = inSize;
+    lzmaCallback.InStream = inStream;
+    lzmaCallback.InCallback.Read = LzmaReadImp;
+    #endif
+
+    if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
+        coder->Properties.Capacity) != LZMA_RESULT_OK)
+      return SZE_FAIL;
+
+    state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+    if (state.Probs == 0)
+      return SZE_OUTOFMEMORY;
+
+    #ifdef _LZMA_OUT_READ
+    if (state.Properties.DictionarySize == 0)
+      state.Dictionary = 0;
+    else
+    {
+      state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
+      if (state.Dictionary == 0)
+      {
+        allocMain->Free(state.Probs);
+        return SZE_OUTOFMEMORY;
+      }
+    }
+    LzmaDecoderInit(&state);
+    #endif
+
+    result = LzmaDecode(&state,
+        #ifdef _LZMA_IN_CB
+        &lzmaCallback.InCallback,
+        #else
+        inBuffer, (size_t)inSize, &inProcessed,
+        #endif
+        outBuffer, (size_t)outSize, &outSizeProcessedLoc,
+	1); // NOTE : Added by Dennis Schridde to make SzDecode be compatible with LzmaStateDecode(.c,.h)
+    *outSizeProcessed = (size_t)outSizeProcessedLoc;
+    allocMain->Free(state.Probs);
+    #ifdef _LZMA_OUT_READ
+    allocMain->Free(state.Dictionary);
+    #endif
+    if (result == LZMA_RESULT_DATA_ERROR)
+      return SZE_DATA_ERROR;
+    if (result != LZMA_RESULT_OK)
+      return SZE_FAIL;
+    return SZ_OK;
+  }
+  return SZE_NOTIMPL;
+}

+ 21 - 0
lzma/7zDecode.h

@@ -0,0 +1,21 @@
+/* 7zDecode.h */
+
+#ifndef __7Z_DECODE_H
+#define __7Z_DECODE_H
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+#ifdef _LZMA_IN_CB
+#include "7zIn.h"
+#endif
+
+SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
+    #ifdef _LZMA_IN_CB
+    ISzInStream *stream,
+    #else
+    const Byte *inBuffer,
+    #endif
+    Byte *outBuffer, size_t outSize, 
+    size_t *outSizeProcessed, ISzAlloc *allocMain);
+
+#endif

+ 5 - 0
lzma/7zHeader.c

@@ -0,0 +1,5 @@
+/*  7zHeader.c */
+
+#include "7zHeader.h"
+
+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};

+ 55 - 0
lzma/7zHeader.h

@@ -0,0 +1,55 @@
+/* 7zHeader.h */
+
+#ifndef __7Z_HEADER_H
+#define __7Z_HEADER_H
+
+#include "7zTypes.h"
+
+#define k7zSignatureSize 6
+extern Byte k7zSignature[k7zSignatureSize];
+
+#define k7zMajorVersion 0
+
+#define k7zStartHeaderSize 0x20
+
+enum EIdEnum
+{
+  k7zIdEnd,
+    
+  k7zIdHeader,
+    
+  k7zIdArchiveProperties,
+    
+  k7zIdAdditionalStreamsInfo,
+  k7zIdMainStreamsInfo,
+  k7zIdFilesInfo,
+  
+  k7zIdPackInfo,
+  k7zIdUnPackInfo,
+  k7zIdSubStreamsInfo,
+  
+  k7zIdSize,
+  k7zIdCRC,
+  
+  k7zIdFolder,
+  
+  k7zIdCodersUnPackSize,
+  k7zIdNumUnPackStream,
+  
+  k7zIdEmptyStream,
+  k7zIdEmptyFile,
+  k7zIdAnti,
+  
+  k7zIdName,
+  k7zIdCreationTime,
+  k7zIdLastAccessTime,
+  k7zIdLastWriteTime,
+  k7zIdWinAttributes,
+  k7zIdComment,
+  
+  k7zIdEncodedHeader,
+  
+  k7zIdStartPos
+};
+
+#endif

+ 1292 - 0
lzma/7zIn.c

@@ -0,0 +1,1292 @@
+/* 7zIn.c */
+
+#include "7zIn.h"
+#include "7zCrc.h"
+#include "7zDecode.h"
+
+#define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; }
+
+void SzArDbExInit(CArchiveDatabaseEx *db)
+{
+  SzArchiveDatabaseInit(&db->Database);
+  db->FolderStartPackStreamIndex = 0;
+  db->PackStreamStartPositions = 0;
+  db->FolderStartFileIndex = 0;
+  db->FileIndexToFolderIndexMap = 0;
+}
+
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *))
+{
+  freeFunc(db->FolderStartPackStreamIndex);
+  freeFunc(db->PackStreamStartPositions);
+  freeFunc(db->FolderStartFileIndex);
+  freeFunc(db->FileIndexToFolderIndexMap);
+  SzArchiveDatabaseFree(&db->Database, freeFunc);
+  SzArDbExInit(db);
+}
+
+/*
+CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const 
+{
+  return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
+}
+
+CFileSize GetFilePackSize(int fileIndex) const
+{
+  int folderIndex = FileIndexToFolderIndexMap[fileIndex];
+  if (folderIndex >= 0)
+  {
+    const CFolder &folderInfo = Folders[folderIndex];
+    if (FolderStartFileIndex[folderIndex] == fileIndex)
+    return GetFolderFullPackSize(folderIndex);
+  }
+  return 0;
+}
+*/
+
+
+SZ_RESULT MySzInAlloc(void **p, size_t size, void * (*allocFunc)(size_t size))
+{
+  if (size == 0)
+    *p = 0;
+  else
+  {
+    *p = allocFunc(size);
+    RINOM(*p);
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size))
+{
+  UInt32 startPos = 0;
+  CFileSize startPosSize = 0;
+  UInt32 i;
+  UInt32 folderIndex = 0;
+  UInt32 indexInFolder = 0;
+  RINOK(MySzInAlloc((void **)&db->FolderStartPackStreamIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc));
+  for(i = 0; i < db->Database.NumFolders; i++)
+  {
+    db->FolderStartPackStreamIndex[i] = startPos;
+    startPos += db->Database.Folders[i].NumPackStreams;
+  }
+
+  RINOK(MySzInAlloc((void **)&db->PackStreamStartPositions, db->Database.NumPackStreams * sizeof(CFileSize), allocFunc));
+
+  for(i = 0; i < db->Database.NumPackStreams; i++)
+  {
+    db->PackStreamStartPositions[i] = startPosSize;
+    startPosSize += db->Database.PackSizes[i];
+  }
+
+  RINOK(MySzInAlloc((void **)&db->FolderStartFileIndex, db->Database.NumFolders * sizeof(UInt32), allocFunc));
+  RINOK(MySzInAlloc((void **)&db->FileIndexToFolderIndexMap, db->Database.NumFiles * sizeof(UInt32), allocFunc));
+
+  for (i = 0; i < db->Database.NumFiles; i++)
+  {
+    CFileItem *file = db->Database.Files + i;
+    int emptyStream = !file->HasStream;
+    if (emptyStream && indexInFolder == 0)
+    {
+      db->FileIndexToFolderIndexMap[i] = (UInt32)-1;
+      continue;
+    }
+    if (indexInFolder == 0)
+    {
+      /*
+      v3.13 incorrectly worked with empty folders
+      v4.07: Loop for skipping empty folders
+      */
+      while(1)
+      {
+        if (folderIndex >= db->Database.NumFolders)
+          return SZE_ARCHIVE_ERROR;
+        db->FolderStartFileIndex[folderIndex] = i;
+        if (db->Database.Folders[folderIndex].NumUnPackStreams != 0)
+          break;
+        folderIndex++;
+      }
+    }
+    db->FileIndexToFolderIndexMap[i] = folderIndex;
+    if (emptyStream)
+      continue;
+    indexInFolder++;
+    if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams)
+    {
+      folderIndex++;
+      indexInFolder = 0;
+    }
+  }
+  return SZ_OK;
+}
+
+
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder)
+{
+  return db->ArchiveInfo.DataStartPosition + 
+    db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder];
+}
+
+CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex)
+{
+  UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex];
+  CFolder *folder = db->Database.Folders + folderIndex;
+  CFileSize size = 0;
+  UInt32 i;
+  for (i = 0; i < folder->NumPackStreams; i++)
+    size += db->Database.PackSizes[packStreamIndex + i];
+  return size;
+}
+
+
+/*
+SZ_RESULT SzReadTime(const CObjectVector<CSzByteBuffer> &dataVector,
+    CObjectVector<CFileItem> &files, UInt64 type)
+{
+  CBoolVector boolVector;
+  RINOK(ReadBoolVector2(files.Size(), boolVector))
+
+  CStreamSwitch streamSwitch;
+  RINOK(streamSwitch.Set(this, &dataVector));
+
+  for(int i = 0; i < files.Size(); i++)
+  {
+    CFileItem &file = files[i];
+    CArchiveFileTime fileTime;
+    bool defined = boolVector[i];
+    if (defined)
+    {
+      UInt32 low, high;
+      RINOK(SzReadUInt32(low));
+      RINOK(SzReadUInt32(high));
+      fileTime.dwLowDateTime = low;
+      fileTime.dwHighDateTime = high;
+    }
+    switch(type)
+    {
+      case k7zIdCreationTime:
+        file.IsCreationTimeDefined = defined;
+        if (defined)
+          file.CreationTime = fileTime;
+        break;
+      case k7zIdLastWriteTime:
+        file.IsLastWriteTimeDefined = defined;
+        if (defined)
+          file.LastWriteTime = fileTime;
+        break;
+      case k7zIdLastAccessTime:
+        file.IsLastAccessTimeDefined = defined;
+        if (defined)
+          file.LastAccessTime = fileTime;
+        break;
+    }
+  }
+  return SZ_OK;
+}
+*/
+
+SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size)
+{
+  #ifdef _LZMA_IN_CB
+  while (size > 0)
+  {
+    Byte *inBuffer;
+    size_t processedSize;
+    RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize));
+    if (processedSize == 0 || processedSize > size)
+      return SZE_FAIL;
+    size -= processedSize;
+    do
+    {
+      *data++ = *inBuffer++;
+    }
+    while (--processedSize != 0);
+  }
+  #else
+  size_t processedSize;
+  RINOK(inStream->Read(inStream, data, size, &processedSize));
+  if (processedSize != size)
+    return SZE_FAIL;
+  #endif
+  return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data)
+{
+  return SafeReadDirect(inStream, data, 1);
+}
+
+SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value)
+{
+  int i;
+  *value = 0;
+  for (i = 0; i < 4; i++)
+  {
+    Byte b;
+    RINOK(SafeReadDirectByte(inStream, &b));
+    *value |= ((UInt32)b << (8 * i));
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value)
+{
+  int i;
+  *value = 0;
+  for (i = 0; i < 8; i++)
+  {
+    Byte b;
+    RINOK(SafeReadDirectByte(inStream, &b));
+    *value |= ((UInt32)b << (8 * i));
+  }
+  return SZ_OK;
+}
+
+int TestSignatureCandidate(Byte *testBytes)
+{
+  size_t i;
+  for (i = 0; i < k7zSignatureSize; i++)
+    if (testBytes[i] != k7zSignature[i])
+      return 0;
+  return 1;
+}
+
+typedef struct _CSzState
+{
+  Byte *Data;
+  size_t Size;
+}CSzData;
+
+SZ_RESULT SzReadByte(CSzData *sd, Byte *b)
+{
+  if (sd->Size == 0)
+    return SZE_ARCHIVE_ERROR;
+  sd->Size--;
+  *b = *sd->Data++;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size)
+{
+  size_t i;
+  for (i = 0; i < size; i++)
+  {
+    RINOK(SzReadByte(sd, data + i));
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value)
+{
+  int i;
+  *value = 0;
+  for (i = 0; i < 4; i++)
+  {
+    Byte b;
+    RINOK(SzReadByte(sd, &b));
+    *value |= ((UInt32)(b) << (8 * i));
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value)
+{
+  Byte firstByte;
+  Byte mask = 0x80;
+  int i;
+  RINOK(SzReadByte(sd, &firstByte));
+  *value = 0;
+  for (i = 0; i < 8; i++)
+  {
+    Byte b;
+    if ((firstByte & mask) == 0)
+    {
+      UInt64 highPart = firstByte & (mask - 1);
+      *value += (highPart << (8 * i));
+      return SZ_OK;
+    }
+    RINOK(SzReadByte(sd, &b));
+    *value |= ((UInt64)b << (8 * i));
+    mask >>= 1;
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value)
+{
+  UInt64 value64;
+  RINOK(SzReadNumber(sd, &value64));
+  *value = (CFileSize)value64;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value)
+{
+  UInt64 value64;
+  RINOK(SzReadNumber(sd, &value64));
+  if (value64 >= 0x80000000)
+    return SZE_NOTIMPL;
+  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2)))
+    return SZE_NOTIMPL;
+  *value = (UInt32)value64;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) 
+{ 
+  return SzReadNumber(sd, value); 
+}
+
+SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size)
+{
+  if (size > sd->Size)
+    return SZE_ARCHIVE_ERROR;
+  sd->Size -= (size_t)size;
+  sd->Data += (size_t)size;
+  return SZ_OK;
+}
+
+SZ_RESULT SzSkeepData(CSzData *sd)
+{
+  UInt64 size;
+  RINOK(SzReadNumber(sd, &size));
+  return SzSkeepDataSize(sd, size);
+}
+
+SZ_RESULT SzReadArchiveProperties(CSzData *sd)
+{
+  while(1)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdEnd)
+      break;
+    SzSkeepData(sd);
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute)
+{
+  while(1)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if (type == attribute)
+      return SZ_OK;
+    if (type == k7zIdEnd)
+      return SZE_ARCHIVE_ERROR;
+    RINOK(SzSkeepData(sd));
+  }
+}
+
+SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+  Byte b = 0;
+  Byte mask = 0;
+  size_t i;
+  RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc));
+  for(i = 0; i < numItems; i++)
+  {
+    if (mask == 0)
+    {
+      RINOK(SzReadByte(sd, &b));
+      mask = 0x80;
+    }
+    (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0);
+    mask >>= 1;
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size))
+{
+  Byte allAreDefined;
+  size_t i;
+  RINOK(SzReadByte(sd, &allAreDefined));
+  if (allAreDefined == 0)
+    return SzReadBoolVector(sd, numItems, v, allocFunc);
+  RINOK(MySzInAlloc((void **)v, numItems * sizeof(Byte), allocFunc));
+  for(i = 0; i < numItems; i++)
+    (*v)[i] = 1;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadHashDigests(
+    CSzData *sd, 
+    size_t numItems,
+    Byte **digestsDefined, 
+    UInt32 **digests, 
+    void * (*allocFunc)(size_t size))
+{
+  size_t i;
+  RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc));
+  RINOK(MySzInAlloc((void **)digests, numItems * sizeof(UInt32), allocFunc));
+  for(i = 0; i < numItems; i++)
+    if ((*digestsDefined)[i])
+    {
+      RINOK(SzReadUInt32(sd, (*digests) + i));
+    }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadPackInfo(
+    CSzData *sd, 
+    CFileSize *dataOffset,
+    UInt32 *numPackStreams,
+    CFileSize **packSizes,
+    Byte **packCRCsDefined,
+    UInt32 **packCRCs,
+    void * (*allocFunc)(size_t size))
+{
+  UInt32 i;
+  RINOK(SzReadSize(sd, dataOffset));
+  RINOK(SzReadNumber32(sd, numPackStreams));
+
+  RINOK(SzWaitAttribute(sd, k7zIdSize));
+
+  RINOK(MySzInAlloc((void **)packSizes, (size_t)*numPackStreams * sizeof(CFileSize), allocFunc));
+
+  for(i = 0; i < *numPackStreams; i++)
+  {
+    RINOK(SzReadSize(sd, (*packSizes) + i));
+  }
+
+  while(1)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdEnd)
+      break;
+    if (type == k7zIdCRC)
+    {
+      RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); 
+      continue;
+    }
+    RINOK(SzSkeepData(sd));
+  }
+  if (*packCRCsDefined == 0)
+  {
+    RINOK(MySzInAlloc((void **)packCRCsDefined, (size_t)*numPackStreams * sizeof(Byte), allocFunc));
+    RINOK(MySzInAlloc((void **)packCRCs, (size_t)*numPackStreams * sizeof(UInt32), allocFunc));
+    for(i = 0; i < *numPackStreams; i++)
+    {
+      (*packCRCsDefined)[i] = 0;
+      (*packCRCs)[i] = 0;
+    }
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadSwitch(CSzData *sd)
+{
+  Byte external;
+  RINOK(SzReadByte(sd, &external));
+  return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR;
+}
+
+SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size))
+{
+  UInt32 numCoders;
+  UInt32 numBindPairs;
+  UInt32 numPackedStreams;
+  UInt32 i;
+  UInt32 numInStreams = 0;
+  UInt32 numOutStreams = 0;
+  RINOK(SzReadNumber32(sd, &numCoders));
+  folder->NumCoders = numCoders;
+
+  RINOK(MySzInAlloc((void **)&folder->Coders, (size_t)numCoders * sizeof(CCoderInfo), allocFunc));
+
+  for (i = 0; i < numCoders; i++)
+    SzCoderInfoInit(folder->Coders + i);
+
+  for (i = 0; i < numCoders; i++)
+  {
+    Byte mainByte;
+    CCoderInfo *coder = folder->Coders + i;
+    {
+      RINOK(SzReadByte(sd, &mainByte));
+      coder->MethodID.IDSize = (Byte)(mainByte & 0xF);
+      RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize));
+      if ((mainByte & 0x10) != 0)
+      {
+        RINOK(SzReadNumber32(sd, &coder->NumInStreams));
+        RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
+      }
+      else
+      {
+        coder->NumInStreams = 1;
+        coder->NumOutStreams = 1;
+      }
+      if ((mainByte & 0x20) != 0)
+      {
+        UInt64 propertiesSize = 0;
+        RINOK(SzReadNumber(sd, &propertiesSize));
+        if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc))
+          return SZE_OUTOFMEMORY;
+        RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize));
+      }
+    }
+    while ((mainByte & 0x80) != 0)
+    {
+      RINOK(SzReadByte(sd, &mainByte));
+      RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
+      if ((mainByte & 0x10) != 0)
+      {
+        UInt32 n;
+        RINOK(SzReadNumber32(sd, &n));
+        RINOK(SzReadNumber32(sd, &n));
+      }
+      if ((mainByte & 0x20) != 0)
+      {
+        UInt64 propertiesSize = 0;
+        RINOK(SzReadNumber(sd, &propertiesSize));
+        RINOK(SzSkeepDataSize(sd, propertiesSize));
+      }
+    }
+    numInStreams += (UInt32)coder->NumInStreams;
+    numOutStreams += (UInt32)coder->NumOutStreams;
+  }
+
+  numBindPairs = numOutStreams - 1;
+  folder->NumBindPairs = numBindPairs;
+
+
+  RINOK(MySzInAlloc((void **)&folder->BindPairs, (size_t)numBindPairs * sizeof(CBindPair), allocFunc));
+
+  for (i = 0; i < numBindPairs; i++)
+  {
+    CBindPair *bindPair = folder->BindPairs + i;;
+    RINOK(SzReadNumber32(sd, &bindPair->InIndex));
+    RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); 
+  }
+
+  numPackedStreams = numInStreams - (UInt32)numBindPairs;
+
+  folder->NumPackStreams = numPackedStreams;
+  RINOK(MySzInAlloc((void **)&folder->PackStreams, (size_t)numPackedStreams * sizeof(UInt32), allocFunc));
+
+  if (numPackedStreams == 1)
+  {
+    UInt32 j;
+    UInt32 pi = 0;
+    for (j = 0; j < numInStreams; j++)
+      if (SzFolderFindBindPairForInStream(folder, j) < 0)
+      {
+        folder->PackStreams[pi++] = j;
+        break;
+      }
+  }
+  else
+    for(i = 0; i < numPackedStreams; i++)
+    {
+      RINOK(SzReadNumber32(sd, folder->PackStreams + i));
+    }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadUnPackInfo(
+    CSzData *sd, 
+    UInt32 *numFolders,
+    CFolder **folders,  /* for allocFunc */
+    void * (*allocFunc)(size_t size),
+    ISzAlloc *allocTemp)
+{
+  UInt32 i;
+  RINOK(SzWaitAttribute(sd, k7zIdFolder));
+  RINOK(SzReadNumber32(sd, numFolders));
+  {
+    RINOK(SzReadSwitch(sd));
+
+
+    RINOK(MySzInAlloc((void **)folders, (size_t)*numFolders * sizeof(CFolder), allocFunc));
+
+    for(i = 0; i < *numFolders; i++)
+      SzFolderInit((*folders) + i);
+
+    for(i = 0; i < *numFolders; i++)
+    {
+      RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc));
+    }
+  }
+
+  RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize));
+
+  for(i = 0; i < *numFolders; i++)
+  {
+    UInt32 j;
+    CFolder *folder = (*folders) + i;
+    UInt32 numOutStreams = SzFolderGetNumOutStreams(folder);
+
+    RINOK(MySzInAlloc((void **)&folder->UnPackSizes, (size_t)numOutStreams * sizeof(CFileSize), allocFunc));
+
+    for(j = 0; j < numOutStreams; j++)
+    {
+      RINOK(SzReadSize(sd, folder->UnPackSizes + j));
+    }
+  }
+
+  while(1)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdEnd)
+      return SZ_OK;
+    if (type == k7zIdCRC)
+    {
+      SZ_RESULT res;
+      Byte *crcsDefined = 0;
+      UInt32 *crcs = 0;
+      res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); 
+      if (res == SZ_OK)
+      {
+        for(i = 0; i < *numFolders; i++)
+        {
+          CFolder *folder = (*folders) + i;
+          folder->UnPackCRCDefined = crcsDefined[i];
+          folder->UnPackCRC = crcs[i];
+        }
+      }
+      allocTemp->Free(crcs);
+      allocTemp->Free(crcsDefined);
+      RINOK(res);
+      continue;
+    }
+    RINOK(SzSkeepData(sd));
+  }
+}
+
+SZ_RESULT SzReadSubStreamsInfo(
+    CSzData *sd, 
+    UInt32 numFolders,
+    CFolder *folders,
+    UInt32 *numUnPackStreams,
+    CFileSize **unPackSizes,
+    Byte **digestsDefined,
+    UInt32 **digests,
+    ISzAlloc *allocTemp)
+{
+  UInt64 type = 0;
+  UInt32 i;
+  UInt32 si = 0;
+  UInt32 numDigests = 0;
+
+  for(i = 0; i < numFolders; i++)
+    folders[i].NumUnPackStreams = 1;
+  *numUnPackStreams = numFolders;
+
+  while(1)
+  {
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdNumUnPackStream)
+    {
+      *numUnPackStreams = 0;
+      for(i = 0; i < numFolders; i++)
+      {
+        UInt32 numStreams;
+        RINOK(SzReadNumber32(sd, &numStreams));
+        folders[i].NumUnPackStreams = numStreams;
+        *numUnPackStreams += numStreams;
+      }
+      continue;
+    }
+    if (type == k7zIdCRC || type == k7zIdSize)
+      break;
+    if (type == k7zIdEnd)
+      break;
+    RINOK(SzSkeepData(sd));
+  }
+
+  if (*numUnPackStreams == 0)
+  {
+    *unPackSizes = 0;
+    *digestsDefined = 0;
+    *digests = 0;
+  }
+  else
+  {
+    *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize));
+    RINOM(*unPackSizes);
+    *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte));
+    RINOM(*digestsDefined);
+    *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32));
+    RINOM(*digests);
+  }
+
+  for(i = 0; i < numFolders; i++)
+  {
+    /*
+    v3.13 incorrectly worked with empty folders
+    v4.07: we check that folder is empty
+    */
+    CFileSize sum = 0;
+    UInt32 j;
+    UInt32 numSubstreams = folders[i].NumUnPackStreams;
+    if (numSubstreams == 0)
+      continue;
+    if (type == k7zIdSize)
+    for (j = 1; j < numSubstreams; j++)
+    {
+      CFileSize size;
+      RINOK(SzReadSize(sd, &size));
+      (*unPackSizes)[si++] = size;
+      sum += size;
+    }
+    (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum;
+  }
+  if (type == k7zIdSize)
+  {
+    RINOK(SzReadID(sd, &type));
+  }
+
+  for(i = 0; i < *numUnPackStreams; i++)
+  {
+    (*digestsDefined)[i] = 0;
+    (*digests)[i] = 0;
+  }
+
+
+  for(i = 0; i < numFolders; i++)
+  {
+    UInt32 numSubstreams = folders[i].NumUnPackStreams;
+    if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
+      numDigests += numSubstreams;
+  }
+
+ 
+  si = 0;
+  while(1)
+  {
+    if (type == k7zIdCRC)
+    {
+      int digestIndex = 0;
+      Byte *digestsDefined2 = 0; 
+      UInt32 *digests2 = 0;
+      SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc);
+      if (res == SZ_OK)
+      {
+        for (i = 0; i < numFolders; i++)
+        {
+          CFolder *folder = folders + i;
+          UInt32 numSubstreams = folder->NumUnPackStreams;
+          if (numSubstreams == 1 && folder->UnPackCRCDefined)
+          {
+            (*digestsDefined)[si] = 1;
+            (*digests)[si] = folder->UnPackCRC;
+            si++;
+          }
+          else
+          {
+            UInt32 j;
+            for (j = 0; j < numSubstreams; j++, digestIndex++)
+            {
+              (*digestsDefined)[si] = digestsDefined2[digestIndex];
+              (*digests)[si] = digests2[digestIndex];
+              si++;
+            }
+          }
+        }
+      }
+      allocTemp->Free(digestsDefined2);
+      allocTemp->Free(digests2);
+      RINOK(res);
+    }
+    else if (type == k7zIdEnd)
+      return SZ_OK;
+    else
+    {
+      RINOK(SzSkeepData(sd));
+    }
+    RINOK(SzReadID(sd, &type));
+  }
+}
+
+
+SZ_RESULT SzReadStreamsInfo(
+    CSzData *sd, 
+    CFileSize *dataOffset,
+    CArchiveDatabase *db,
+    UInt32 *numUnPackStreams,
+    CFileSize **unPackSizes, /* allocTemp */
+    Byte **digestsDefined,   /* allocTemp */
+    UInt32 **digests,        /* allocTemp */
+    void * (*allocFunc)(size_t size),
+    ISzAlloc *allocTemp)
+{
+  while(1)
+  {
+    UInt64 type;
+    RINOK(SzReadID(sd, &type));
+    if ((UInt64)(int)type != type)
+      return SZE_FAIL;
+    switch((int)type)
+    {
+      case k7zIdEnd:
+        return SZ_OK;
+      case k7zIdPackInfo:
+      {
+        RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, 
+            &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc));
+        break;
+      }
+      case k7zIdUnPackInfo:
+      {
+        RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp));
+        break;
+      }
+      case k7zIdSubStreamsInfo:
+      {
+        RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, 
+            numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp));
+        break;
+      }
+      default:
+        return SZE_FAIL;
+    }
+  }
+}
+
+Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, 
+    void * (*allocFunc)(size_t size))
+{
+  UInt32 i;
+  for(i = 0; i < numFiles; i++)
+  {
+    UInt32 len = 0;
+    UInt32 pos = 0;
+    CFileItem *file = files + i;
+    while(pos + 2 <= sd->Size)
+    {
+      int numAdds;
+      UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+      pos += 2;
+      len++;
+      if (value == 0)
+        break;
+      if (value < 0x80)
+        continue;
+      if (value >= 0xD800 && value < 0xE000)
+      {
+        UInt32 c2;
+        if (value >= 0xDC00)
+          return SZE_ARCHIVE_ERROR;
+        if (pos + 2 > sd->Size)
+          return SZE_ARCHIVE_ERROR;
+        c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
+        pos += 2;
+        if (c2 < 0xDC00 || c2 >= 0xE000)
+          return SZE_ARCHIVE_ERROR;
+        value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+      }
+      for (numAdds = 1; numAdds < 5; numAdds++)
+        if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+          break;
+      len += numAdds;
+    }
+
+    RINOK(MySzInAlloc((void **)&file->Name, (size_t)len * sizeof(char), allocFunc));
+
+    len = 0;
+    while(2 <= sd->Size)
+    {
+      int numAdds;
+      UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+      SzSkeepDataSize(sd, 2);
+      if (value < 0x80)
+      {
+        file->Name[len++] = (char)value;
+        if (value == 0)
+          break;
+        continue;
+      }
+      if (value >= 0xD800 && value < 0xE000)
+      {
+        UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
+        SzSkeepDataSize(sd, 2);
+        value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
+      }
+      for (numAdds = 1; numAdds < 5; numAdds++)
+        if (value < (((UInt32)1) << (numAdds * 5 + 6)))
+          break;
+      file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
+      do
+      {
+        numAdds--;
+        file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
+      }
+      while(numAdds > 0);
+
+      len += numAdds;
+    }
+  }
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadHeader2(
+    CSzData *sd, 
+    CArchiveDatabaseEx *db,   /* allocMain */
+    CFileSize **unPackSizes,  /* allocTemp */
+    Byte **digestsDefined,    /* allocTemp */
+    UInt32 **digests,         /* allocTemp */
+    Byte **emptyStreamVector, /* allocTemp */
+    Byte **emptyFileVector,   /* allocTemp */
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp)
+{
+  UInt64 type;
+  UInt32 numUnPackStreams = 0;
+  UInt32 numFiles = 0;
+  CFileItem *files = 0;
+  UInt32 numEmptyStreams = 0;
+  UInt32 i;
+
+  RINOK(SzReadID(sd, &type));
+
+  if (type == k7zIdArchiveProperties)
+  {
+    RINOK(SzReadArchiveProperties(sd));
+    RINOK(SzReadID(sd, &type));
+  }
+ 
+ 
+  if (type == k7zIdMainStreamsInfo)
+  {
+    RINOK(SzReadStreamsInfo(sd,
+        &db->ArchiveInfo.DataStartPosition,
+        &db->Database, 
+        &numUnPackStreams,
+        unPackSizes,
+        digestsDefined,
+        digests, allocMain->Alloc, allocTemp));
+    db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader;
+    RINOK(SzReadID(sd, &type));
+  }
+
+  if (type == k7zIdEnd)
+    return SZ_OK;
+  if (type != k7zIdFilesInfo)
+    return SZE_ARCHIVE_ERROR;
+  
+  RINOK(SzReadNumber32(sd, &numFiles));
+  db->Database.NumFiles = numFiles;
+
+  RINOK(MySzInAlloc((void **)&files, (size_t)numFiles * sizeof(CFileItem), allocMain->Alloc));
+
+  db->Database.Files = files;
+  for(i = 0; i < numFiles; i++)
+    SzFileInit(files + i);
+
+  while(1)
+  {
+    UInt64 type;
+    UInt64 size;
+    RINOK(SzReadID(sd, &type));
+    if (type == k7zIdEnd)
+      break;
+    RINOK(SzReadNumber(sd, &size));
+
+    if ((UInt64)(int)type != type)
+    {
+      RINOK(SzSkeepDataSize(sd, size));
+    }
+    else
+    switch((int)type)
+    {
+      case k7zIdName:
+      {
+        RINOK(SzReadSwitch(sd));
+        RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc))
+        break;
+      }
+      case k7zIdEmptyStream:
+      {
+        RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc));
+        numEmptyStreams = 0;
+        for (i = 0; i < numFiles; i++)
+          if ((*emptyStreamVector)[i])
+            numEmptyStreams++;
+        break;
+      }
+      case k7zIdEmptyFile:
+      {
+        RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc));
+        break;
+      }
+      default:
+      {
+        RINOK(SzSkeepDataSize(sd, size));
+      }
+    }
+  }
+
+  {
+    UInt32 emptyFileIndex = 0;
+    UInt32 sizeIndex = 0;
+    for(i = 0; i < numFiles; i++)
+    {
+      CFileItem *file = files + i;
+      file->IsAnti = 0;
+      if (*emptyStreamVector == 0)
+        file->HasStream = 1;
+      else
+        file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1);
+      if(file->HasStream)
+      {
+        file->IsDirectory = 0;
+        file->Size = (*unPackSizes)[sizeIndex];
+        file->FileCRC = (*digests)[sizeIndex];
+        file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex];
+        sizeIndex++;
+      }
+      else
+      {
+        if (*emptyFileVector == 0)
+          file->IsDirectory = 1;
+        else
+          file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
+        emptyFileIndex++;
+        file->Size = 0;
+        file->IsFileCRCDefined = 0;
+      }
+    }
+  }
+  return SzArDbExFill(db, allocMain->Alloc);
+}
+
+SZ_RESULT SzReadHeader(
+    CSzData *sd, 
+    CArchiveDatabaseEx *db, 
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp)
+{
+  CFileSize *unPackSizes = 0;
+  Byte *digestsDefined = 0;
+  UInt32 *digests = 0;
+  Byte *emptyStreamVector = 0;
+  Byte *emptyFileVector = 0;
+  SZ_RESULT res = SzReadHeader2(sd, db, 
+      &unPackSizes, &digestsDefined, &digests,
+      &emptyStreamVector, &emptyFileVector,
+      allocMain, allocTemp);
+  allocTemp->Free(unPackSizes);
+  allocTemp->Free(digestsDefined);
+  allocTemp->Free(digests);
+  allocTemp->Free(emptyStreamVector);
+  allocTemp->Free(emptyFileVector);
+  return res;
+} 
+
+SZ_RESULT SzReadAndDecodePackedStreams2(
+    ISzInStream *inStream, 
+    CSzData *sd,
+    CSzByteBuffer *outBuffer,
+    CFileSize baseOffset, 
+    CArchiveDatabase *db,
+    CFileSize **unPackSizes,
+    Byte **digestsDefined,
+    UInt32 **digests,
+    #ifndef _LZMA_IN_CB
+    Byte **inBuffer,
+    #endif
+    ISzAlloc *allocTemp)
+{
+
+  UInt32 numUnPackStreams = 0;
+  CFileSize dataStartPos;
+  CFolder *folder;
+  #ifndef _LZMA_IN_CB
+  CFileSize packSize = 0;
+  UInt32 i = 0;
+  #endif
+  CFileSize unPackSize;
+  size_t outRealSize;
+  SZ_RESULT res;
+
+  RINOK(SzReadStreamsInfo(sd, &dataStartPos, db,
+      &numUnPackStreams,  unPackSizes, digestsDefined, digests, 
+      allocTemp->Alloc, allocTemp));
+  
+  dataStartPos += baseOffset;
+  if (db->NumFolders != 1)
+    return SZE_ARCHIVE_ERROR;
+
+  folder = db->Folders;
+  unPackSize = SzFolderGetUnPackSize(folder);
+  
+  RINOK(inStream->Seek(inStream, dataStartPos));
+
+  #ifndef _LZMA_IN_CB
+  for (i = 0; i < db->NumPackStreams; i++)
+    packSize += db->PackSizes[i];
+
+  RINOK(MySzInAlloc((void **)inBuffer, (size_t)packSize, allocTemp->Alloc));
+
+  RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize));
+  #endif
+
+  if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc))
+    return SZE_OUTOFMEMORY;
+  
+  res = SzDecode(db->PackSizes, folder, 
+          #ifdef _LZMA_IN_CB
+          inStream,
+          #else
+          *inBuffer, 
+          #endif
+          outBuffer->Items, (size_t)unPackSize,
+          &outRealSize, allocTemp);
+  RINOK(res)
+  if (outRealSize != (UInt32)unPackSize)
+    return SZE_FAIL;
+  if (folder->UnPackCRCDefined)
+    if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize))
+      return SZE_FAIL;
+  return SZ_OK;
+}
+
+SZ_RESULT SzReadAndDecodePackedStreams(
+    ISzInStream *inStream, 
+    CSzData *sd,
+    CSzByteBuffer *outBuffer,
+    CFileSize baseOffset, 
+    ISzAlloc *allocTemp)
+{
+  CArchiveDatabase db;
+  CFileSize *unPackSizes = 0;
+  Byte *digestsDefined = 0;
+  UInt32 *digests = 0;
+  #ifndef _LZMA_IN_CB
+  Byte *inBuffer = 0;
+  #endif
+  SZ_RESULT res;
+  SzArchiveDatabaseInit(&db);
+  res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, 
+    &db, &unPackSizes, &digestsDefined, &digests, 
+    #ifndef _LZMA_IN_CB
+    &inBuffer,
+    #endif
+    allocTemp);
+  SzArchiveDatabaseFree(&db, allocTemp->Free);
+  allocTemp->Free(unPackSizes);
+  allocTemp->Free(digestsDefined);
+  allocTemp->Free(digests);
+  #ifndef _LZMA_IN_CB
+  allocTemp->Free(inBuffer);
+  #endif
+  return res;
+}
+
+SZ_RESULT SzArchiveOpen2(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp)
+{
+  Byte signature[k7zSignatureSize];
+  Byte version;
+  UInt32 crcFromArchive;
+  UInt64 nextHeaderOffset;
+  UInt64 nextHeaderSize;
+  UInt32 nextHeaderCRC;
+  UInt32 crc;
+  CFileSize pos = 0;
+  CSzByteBuffer buffer;
+  CSzData sd;
+  SZ_RESULT res;
+
+  RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize));
+
+  if (!TestSignatureCandidate(signature))
+    return SZE_ARCHIVE_ERROR;
+
+  /*
+  db.Clear();
+  db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
+  */
+  RINOK(SafeReadDirectByte(inStream, &version));
+  if (version != k7zMajorVersion)
+    return SZE_ARCHIVE_ERROR;
+  RINOK(SafeReadDirectByte(inStream, &version));
+
+  RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive));
+
+  CrcInit(&crc);
+  RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset));
+  CrcUpdateUInt64(&crc, nextHeaderOffset);
+  RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize));
+  CrcUpdateUInt64(&crc, nextHeaderSize);
+  RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC));
+  CrcUpdateUInt32(&crc, nextHeaderCRC);
+
+  pos = k7zStartHeaderSize;
+  db->ArchiveInfo.StartPositionAfterHeader = pos;
+  
+  if (CrcGetDigest(&crc) != crcFromArchive)
+    return SZE_ARCHIVE_ERROR;
+
+  if (nextHeaderSize == 0)
+    return SZ_OK;
+
+  RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset)));
+
+  if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc))
+    return SZE_OUTOFMEMORY;
+
+  res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize);
+  if (res == SZ_OK)
+  {
+    if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize))
+    {
+      while (1)
+      {
+        UInt64 type;
+        sd.Data = buffer.Items;
+        sd.Size = buffer.Capacity;
+        res = SzReadID(&sd, &type);
+        if (res != SZ_OK)
+          break;
+        if (type == k7zIdHeader)
+        {
+          res = SzReadHeader(&sd, db, allocMain, allocTemp);
+          break;
+        }
+        if (type != k7zIdEncodedHeader)
+        {
+          res = SZE_ARCHIVE_ERROR;
+          break;
+        }
+        {
+          CSzByteBuffer outBuffer;
+          res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, 
+              db->ArchiveInfo.StartPositionAfterHeader, 
+              allocTemp);
+          if (res != SZ_OK)
+          {
+            SzByteBufferFree(&outBuffer, allocTemp->Free);
+            break;
+          }
+          SzByteBufferFree(&buffer, allocTemp->Free);
+          buffer.Items = outBuffer.Items;
+          buffer.Capacity = outBuffer.Capacity;
+        }
+      }
+    }
+  }
+  SzByteBufferFree(&buffer, allocTemp->Free);
+  return res;
+}
+
+SZ_RESULT SzArchiveOpen(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp)
+{
+  SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp);
+  if (res != SZ_OK)
+    SzArDbExFree(db, allocMain->Free);
+  return res;
+}

+ 55 - 0
lzma/7zIn.h

@@ -0,0 +1,55 @@
+/* 7zIn.h */
+
+#ifndef __7Z_IN_H
+#define __7Z_IN_H
+
+#include "7zHeader.h"
+#include "7zItem.h"
+#include "7zAlloc.h"
+ 
+typedef struct _CInArchiveInfo
+{
+  CFileSize StartPositionAfterHeader; 
+  CFileSize DataStartPosition;
+}CInArchiveInfo;
+
+typedef struct _CArchiveDatabaseEx
+{
+  CArchiveDatabase Database;
+  CInArchiveInfo ArchiveInfo;
+  UInt32 *FolderStartPackStreamIndex;
+  CFileSize *PackStreamStartPositions;
+  UInt32 *FolderStartFileIndex;
+  UInt32 *FileIndexToFolderIndexMap;
+}CArchiveDatabaseEx;
+
+void SzArDbExInit(CArchiveDatabaseEx *db);
+void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *));
+CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder);
+CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex);
+
+typedef struct _ISzInStream
+{
+  #ifdef _LZMA_IN_CB
+  SZ_RESULT (*Read)(
+      void *object,           /* pointer to ISzInStream itself */
+      void **buffer,          /* out: pointer to buffer with data */
+      size_t maxRequiredSize, /* max required size to read */
+      size_t *processedSize); /* real processed size. 
+                                 processedSize can be less than maxRequiredSize.
+                                 If processedSize == 0, then there are no more 
+                                 bytes in stream. */
+  #else
+  SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize);
+  #endif
+  SZ_RESULT (*Seek)(void *object, CFileSize pos);
+} ISzInStream;
+
+ 
+int SzArchiveOpen(
+    ISzInStream *inStream, 
+    CArchiveDatabaseEx *db,
+    ISzAlloc *allocMain, 
+    ISzAlloc *allocTemp);
+ 
+#endif

+ 133 - 0
lzma/7zItem.c

@@ -0,0 +1,133 @@
+/* 7zItem.c */
+
+#include "7zItem.h"
+#include "7zAlloc.h"
+
+void SzCoderInfoInit(CCoderInfo *coder)
+{
+  SzByteBufferInit(&coder->Properties);
+}
+
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
+{
+  SzByteBufferFree(&coder->Properties, freeFunc);
+  SzCoderInfoInit(coder);
+}
+
+void SzFolderInit(CFolder *folder)
+{
+  folder->NumCoders = 0;
+  folder->Coders = 0;
+  folder->NumBindPairs = 0;
+  folder->BindPairs = 0;
+  folder->NumPackStreams = 0;
+  folder->PackStreams = 0;
+  folder->UnPackSizes = 0;
+  folder->UnPackCRCDefined = 0;
+  folder->UnPackCRC = 0;
+  folder->NumUnPackStreams = 0;
+}
+
+void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
+{
+  UInt32 i;
+  for (i = 0; i < folder->NumCoders; i++)
+    SzCoderInfoFree(&folder->Coders[i], freeFunc);
+  freeFunc(folder->Coders);
+  freeFunc(folder->BindPairs);
+  freeFunc(folder->PackStreams);
+  freeFunc(folder->UnPackSizes);
+  SzFolderInit(folder);
+}
+
+UInt32 SzFolderGetNumOutStreams(CFolder *folder)
+{
+  UInt32 result = 0;
+  UInt32 i;
+  for (i = 0; i < folder->NumCoders; i++)
+    result += folder->Coders[i].NumOutStreams;
+  return result;
+}
+
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
+{
+  UInt32 i;
+  for(i = 0; i < folder->NumBindPairs; i++)
+    if (folder->BindPairs[i].InIndex == inStreamIndex)
+      return i;
+  return -1;
+}
+
+
+int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
+{
+  UInt32 i;
+  for(i = 0; i < folder->NumBindPairs; i++)
+    if (folder->BindPairs[i].OutIndex == outStreamIndex)
+      return i;
+  return -1;
+}
+
+CFileSize SzFolderGetUnPackSize(CFolder *folder)
+{ 
+  int i = (int)SzFolderGetNumOutStreams(folder);
+  if (i == 0)
+    return 0;
+  for (i--; i >= 0; i--)
+    if (SzFolderFindBindPairForOutStream(folder, i) < 0)
+      return folder->UnPackSizes[i];
+  /* throw 1; */
+  return 0;
+}
+
+/*
+int FindPackStreamArrayIndex(int inStreamIndex) const
+{
+  for(int i = 0; i < PackStreams.Size(); i++)
+  if (PackStreams[i] == inStreamIndex)
+    return i;
+  return -1;
+}
+*/
+
+void SzFileInit(CFileItem *fileItem)
+{
+  fileItem->IsFileCRCDefined = 0;
+  fileItem->HasStream = 1;
+  fileItem->IsDirectory = 0;
+  fileItem->IsAnti = 0;
+  fileItem->Name = 0;
+}
+
+void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
+{
+  freeFunc(fileItem->Name);
+  SzFileInit(fileItem);
+}
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db)
+{
+  db->NumPackStreams = 0;
+  db->PackSizes = 0;
+  db->PackCRCsDefined = 0;
+  db->PackCRCs = 0;
+  db->NumFolders = 0;
+  db->Folders = 0;
+  db->NumFiles = 0;
+  db->Files = 0;
+}
+
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
+{
+  UInt32 i;
+  for (i = 0; i < db->NumFolders; i++)
+    SzFolderFree(&db->Folders[i], freeFunc);
+  for (i = 0; i < db->NumFiles; i++)
+    SzFileFree(&db->Files[i], freeFunc);
+  freeFunc(db->PackSizes);
+  freeFunc(db->PackCRCsDefined);
+  freeFunc(db->PackCRCs);
+  freeFunc(db->Folders);
+  freeFunc(db->Files);
+  SzArchiveDatabaseInit(db);
+}

+ 90 - 0
lzma/7zItem.h

@@ -0,0 +1,90 @@
+/* 7zItem.h */
+
+#ifndef __7Z_ITEM_H
+#define __7Z_ITEM_H
+
+#include "7zMethodID.h"
+#include "7zHeader.h"
+#include "7zBuffer.h"
+
+typedef struct _CCoderInfo
+{
+  UInt32 NumInStreams;
+  UInt32 NumOutStreams;
+  CMethodID MethodID;
+  CSzByteBuffer Properties;
+}CCoderInfo;
+
+void SzCoderInfoInit(CCoderInfo *coder);
+void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p));
+
+typedef struct _CBindPair
+{
+  UInt32 InIndex;
+  UInt32 OutIndex;
+}CBindPair;
+
+typedef struct _CFolder
+{
+  UInt32 NumCoders;
+  CCoderInfo *Coders;
+  UInt32 NumBindPairs;
+  CBindPair *BindPairs;
+  UInt32 NumPackStreams; 
+  UInt32 *PackStreams;
+  CFileSize *UnPackSizes;
+  int UnPackCRCDefined;
+  UInt32 UnPackCRC;
+
+  UInt32 NumUnPackStreams;
+}CFolder;
+
+void SzFolderInit(CFolder *folder);
+CFileSize SzFolderGetUnPackSize(CFolder *folder);
+int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex);
+UInt32 SzFolderGetNumOutStreams(CFolder *folder);
+CFileSize SzFolderGetUnPackSize(CFolder *folder);
+
+/* #define CArchiveFileTime UInt64 */
+
+typedef struct _CFileItem
+{
+  /*
+  CArchiveFileTime LastWriteTime;
+  CFileSize StartPos;
+  UInt32 Attributes; 
+  */
+  CFileSize Size;
+  UInt32 FileCRC;
+  char *Name;
+
+  Byte IsFileCRCDefined;
+  Byte HasStream;
+  Byte IsDirectory;
+  Byte IsAnti;
+  /*
+  int AreAttributesDefined;
+  int IsLastWriteTimeDefined;
+  int IsStartPosDefined;
+  */
+}CFileItem;
+
+void SzFileInit(CFileItem *fileItem);
+
+typedef struct _CArchiveDatabase
+{
+  UInt32 NumPackStreams;
+  CFileSize *PackSizes;
+  Byte *PackCRCsDefined;
+  UInt32 *PackCRCs;
+  UInt32 NumFolders;
+  CFolder *Folders;
+  UInt32 NumFiles;
+  CFileItem *Files;
+}CArchiveDatabase;
+
+void SzArchiveDatabaseInit(CArchiveDatabase *db);
+void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *));
+
+
+#endif

+ 14 - 0
lzma/7zMethodID.c

@@ -0,0 +1,14 @@
+/* 7zMethodID.c */
+
+#include "7zMethodID.h"
+
+int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
+{
+  int i;
+  if (a1->IDSize != a2->IDSize)
+    return 0;
+  for (i = 0; i < a1->IDSize; i++)
+    if (a1->ID[i] != a2->ID[i])
+      return 0;
+  return 1;
+}

+ 18 - 0
lzma/7zMethodID.h

@@ -0,0 +1,18 @@
+/* 7zMethodID.h */
+
+#ifndef __7Z_METHOD_ID_H
+#define __7Z_METHOD_ID_H
+
+#include "7zTypes.h"
+
+#define kMethodIDSize 15
+  
+typedef struct _CMethodID
+{
+  Byte ID[kMethodIDSize];
+  Byte IDSize;
+} CMethodID;
+
+int AreMethodsEqual(CMethodID *a1, CMethodID *a2);
+
+#endif

+ 61 - 0
lzma/7zTypes.h

@@ -0,0 +1,61 @@
+/* 7zTypes.h */
+
+#ifndef __COMMON_TYPES_H
+#define __COMMON_TYPES_H
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#ifndef UInt16
+#define UInt16 unsigned short
+#endif
+
+/* #define _SZ_NO_INT_64 */
+/* define it your compiler doesn't support long long int */
+
+#ifdef _SZ_NO_INT_64
+#define UInt64 unsigned long
+#else
+#ifdef _MSC_VER
+#define UInt64 unsigned __int64
+#else
+#define UInt64 unsigned long long int
+#endif
+#endif
+
+
+/* #define _SZ_FILE_SIZE_64 */
+/* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/
+
+#ifndef CFileSize
+#ifdef _SZ_FILE_SIZE_64
+#define CFileSize UInt64
+#else
+#define CFileSize UInt32
+#endif
+#endif
+
+#define SZ_RESULT int
+
+#define SZ_OK (0)
+#define SZE_DATA_ERROR (1)
+#define SZE_OUTOFMEMORY (2)
+#define SZE_CRC_ERROR (3)
+
+#define SZE_NOTIMPL (4)
+#define SZE_FAIL (5)
+
+#define SZE_ARCHIVE_ERROR (6)
+
+#define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; }
+
+#endif

+ 97 - 0
lzma/LZMA-LICENSE.txt

@@ -0,0 +1,97 @@
+(These are the licensing details for this directory, taken from lzma.txt in
+ the original source distribution. The basic gist is you can do what you want
+ with this code, including sell it in a closed-source app...changes to LZMA
+ itself must be released as source code, which in the case of PhysicsFS, you
+ can just point people to our source code repository unless you make further
+ changes yourself.  --ryan.)
+
+
+LZMA SDK 4.27
+-------------
+
+LZMA SDK 4.27  Copyright (C) 1999-2005 Igor Pavlov
+
+LZMA SDK provides developers with documentation, source code,
+and sample code necessary to write software that uses LZMA compression. 
+
+LZMA is default and general compression method of 7z format
+in 7-Zip compression program (www.7-zip.org). LZMA provides high 
+compression ratio and very fast decompression.
+
+LZMA is an improved version of famous LZ77 compression algorithm. 
+It was improved in way of maximum increasing of compression ratio,
+keeping high decompression speed and low memory requirements for 
+decompressing.
+
+
+
+LICENSE
+-------
+
+LZMA SDK is licensed under two licenses:
+
+1) GNU Lesser General Public License (GNU LGPL)
+2) Common Public License (CPL)
+
+It means that you can select one of these two licenses and 
+follow rules of that license.
+
+SPECIAL EXCEPTION
+Igor Pavlov, as the author of this code, expressly permits you 
+to statically or dynamically link your code (or bind by name) 
+to the files from LZMA SDK without subjecting your linked 
+code to the terms of the CPL or GNU LGPL. 
+Any modifications or additions to files from LZMA SDK, however, 
+are subject to the GNU LGPL or CPL terms.
+
+
+SPECIAL EXCEPTION allows you to use LZMA SDK in applications with closed code, 
+while you keep LZMA SDK code unmodified.
+
+
+SPECIAL EXCEPTION #2: Igor Pavlov, as the author of this code, expressly permits 
+you to use this code under the same terms and conditions contained in the License 
+Agreement you have for any previous version of LZMA SDK developed by Igor Pavlov.
+
+SPECIAL EXCEPTION #2 allows owners of proprietary licenses to use latest version 
+of LZMA SDK as update for previous versions.
+
+
+SPECIAL EXCEPTION #3: Igor Pavlov, as the author of this code, expressly permits 
+you to use code of examples (LzmaTest.c, LzmaStateTest.c, LzmaAlone.cpp) as 
+public domain code. 
+
+
+GNU LGPL and CPL licenses are pretty similar and both these
+licenses are classified as 
+
+1) "Free software licenses" at http://www.gnu.org/ 
+2) "OSI-approved" at http://www.opensource.org/
+
+
+
+LZMA SDK also can be available under a proprietary license which 
+can include:
+
+1) Right to modify code without subjecting modified code to the 
+terms of the CPL or GNU LGPL
+2) Technical support for code
+
+To request such proprietary license or any additional consultations,
+send email message from that page:
+http://www.7-zip.org/support.html
+
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+You should have received a copy of the Common Public License
+along with this library.
+
+
+
+---
+
+http://www.7-zip.org
+http://www.7-zip.org/support.html

+ 521 - 0
lzma/LzmaStateDecode.c

@@ -0,0 +1,521 @@
+/*
+  LzmaStateDecode.c
+  LZMA Decoder (State version)
+
+  LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this Code, expressly permits you to
+  statically or dynamically link your Code (or bind by name) to the
+  interfaces of this file without subjecting your linked Code to the
+  terms of the CPL or GNU LGPL. Any modifications or additions
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaStateDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT Code = 0; Range = 0xFFFFFFFF; \
+  { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }}
+
+#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+  { UpdateBit0(p); mi <<= 1; A0; } else \
+  { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+  { int i = numLevels; res = 1; \
+  do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+  res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+/* kRequiredInBufferSize = number of required input bytes for worst case:
+   longest match with longest distance.
+   kLzmaInBufferSize must be larger than kRequiredInBufferSize
+   23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE)
+*/
+
+#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8)
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+  unsigned char prop0;
+  if (size < LZMA_PROPERTIES_SIZE)
+    return LZMA_RESULT_DATA_ERROR;
+  prop0 = propsData[0];
+  if (prop0 >= (9 * 5 * 5))
+    return LZMA_RESULT_DATA_ERROR;
+  {
+    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+    propsRes->lc = prop0;
+    /*
+    unsigned char remainder = (unsigned char)(prop0 / 9);
+    propsRes->lc = prop0 % 9;
+    propsRes->pb = remainder / 5;
+    propsRes->lp = remainder % 5;
+    */
+  }
+
+  {
+    int i;
+    propsRes->DictionarySize = 0;
+    for (i = 0; i < 4; i++)
+      propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+    if (propsRes->DictionarySize == 0)
+      propsRes->DictionarySize = 1;
+    return LZMA_RESULT_OK;
+  }
+}
+
+int LzmaDecode(
+    CLzmaDecoderState *vs,
+    const unsigned char *inStream, size_t inSize, size_t *inSizeProcessed,
+    unsigned char *outStream, size_t outSize, size_t *outSizeProcessed,
+    int finishDecoding)
+{
+  UInt32 Range = vs->Range;
+  UInt32 Code = vs->Code;
+
+  unsigned char *Buffer = vs->Buffer;
+  int BufferSize = vs->BufferSize; /* don't change it to unsigned int */
+  CProb *p = vs->Probs;
+
+  int state = vs->State;
+  unsigned char previousByte;
+  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+  size_t nowPos = 0;
+  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+  int lc = vs->Properties.lc;
+  int len = vs->RemainLen;
+  UInt32 globalPos = vs->GlobalPos;
+  UInt32 distanceLimit = vs->DistanceLimit;
+
+  unsigned char *dictionary = vs->Dictionary;
+  UInt32 dictionarySize = vs->Properties.DictionarySize;
+  UInt32 dictionaryPos = vs->DictionaryPos;
+
+  unsigned char tempDictionary[4];
+
+  (*inSizeProcessed) = 0;
+  (*outSizeProcessed) = 0;
+  if (len == kLzmaStreamWasFinishedId)
+    return LZMA_RESULT_OK;
+
+  if (dictionarySize == 0)
+  {
+    dictionary = tempDictionary;
+    dictionarySize = 1;
+    tempDictionary[0] = vs->TempDictionary[0];
+  }
+
+  if (len == kLzmaNeedInitId)
+  {
+    while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+    {
+      Buffer[BufferSize++] = *inStream++;
+      (*inSizeProcessed)++;
+      inSize--;
+    }
+    if (BufferSize < 5)
+    {
+      vs->BufferSize = BufferSize;
+      return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK;
+    }
+    {
+      UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+      UInt32 i;
+      for (i = 0; i < numProbs; i++)
+        p[i] = kBitModelTotal >> 1;
+      rep0 = rep1 = rep2 = rep3 = 1;
+      state = 0;
+      globalPos = 0;
+      distanceLimit = 0;
+      dictionaryPos = 0;
+      dictionary[dictionarySize - 1] = 0;
+      RC_INIT;
+    }
+    len = 0;
+  }
+  while(len != 0 && nowPos < outSize)
+  {
+    UInt32 pos = dictionaryPos - rep0;
+    if (pos >= dictionarySize)
+      pos += dictionarySize;
+    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+    if (++dictionaryPos == dictionarySize)
+      dictionaryPos = 0;
+    len--;
+  }
+  if (dictionaryPos == 0)
+    previousByte = dictionary[dictionarySize - 1];
+  else
+    previousByte = dictionary[dictionaryPos - 1];
+
+  while(1)
+  {
+    int bufferPos = (int)(Buffer - vs->Buffer);
+    if (BufferSize - bufferPos < kRequiredInBufferSize)
+    {
+      int i;
+      BufferSize -= bufferPos;
+      if (BufferSize < 0)
+        return LZMA_RESULT_DATA_ERROR;
+      for (i = 0; i < BufferSize; i++)
+        vs->Buffer[i] = Buffer[i];
+      Buffer = vs->Buffer;
+      while (inSize > 0 && BufferSize < kLzmaInBufferSize)
+      {
+        Buffer[BufferSize++] = *inStream++;
+        (*inSizeProcessed)++;
+        inSize--;
+      }
+      if (BufferSize < kRequiredInBufferSize && !finishDecoding)
+        break;
+    }
+    if (nowPos >= outSize)
+      break;
+    {
+    CProb *prob;
+    UInt32 bound;
+    int posState = (int)((nowPos + globalPos) & posStateMask);
+
+    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+    IfBit0(prob)
+    {
+      int symbol = 1;
+      UpdateBit0(prob)
+      prob = p + Literal + (LZMA_LIT_SIZE *
+        ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+      if (state >= kNumLitStates)
+      {
+        int matchByte;
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        matchByte = dictionary[pos];
+        do
+        {
+          int bit;
+          CProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & 0x100);
+          probLit = prob + 0x100 + bit + symbol;
+          RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+        }
+        while (symbol < 0x100);
+      }
+      while (symbol < 0x100)
+      {
+        CProb *probLit = prob + symbol;
+        RC_GET_BIT(probLit, symbol)
+      }
+      previousByte = (unsigned char)symbol;
+
+      outStream[nowPos++] = previousByte;
+      if (distanceLimit < dictionarySize)
+        distanceLimit++;
+
+      dictionary[dictionaryPos] = previousByte;
+      if (++dictionaryPos == dictionarySize)
+        dictionaryPos = 0;
+      if (state < 4) state = 0;
+      else if (state < 10) state -= 3;
+      else state -= 6;
+    }
+    else
+    {
+      UpdateBit1(prob);
+      prob = p + IsRep + state;
+      IfBit0(prob)
+      {
+        UpdateBit0(prob);
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        state = state < kNumLitStates ? 0 : 3;
+        prob = p + LenCoder;
+      }
+      else
+      {
+        UpdateBit1(prob);
+        prob = p + IsRepG0 + state;
+        IfBit0(prob)
+        {
+          UpdateBit0(prob);
+          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IfBit0(prob)
+          {
+            UInt32 pos;
+            UpdateBit0(prob);
+            if (distanceLimit == 0)
+              return LZMA_RESULT_DATA_ERROR;
+            if (distanceLimit < dictionarySize)
+              distanceLimit++;
+            state = state < kNumLitStates ? 9 : 11;
+            pos = dictionaryPos - rep0;
+            if (pos >= dictionarySize)
+              pos += dictionarySize;
+            previousByte = dictionary[pos];
+            dictionary[dictionaryPos] = previousByte;
+            if (++dictionaryPos == dictionarySize)
+              dictionaryPos = 0;
+            outStream[nowPos++] = previousByte;
+            continue;
+          }
+          else
+          {
+            UpdateBit1(prob);
+          }
+        }
+        else
+        {
+          UInt32 distance;
+          UpdateBit1(prob);
+          prob = p + IsRepG1 + state;
+          IfBit0(prob)
+          {
+            UpdateBit0(prob);
+            distance = rep1;
+          }
+          else
+          {
+            UpdateBit1(prob);
+            prob = p + IsRepG2 + state;
+            IfBit0(prob)
+            {
+              UpdateBit0(prob);
+              distance = rep2;
+            }
+            else
+            {
+              UpdateBit1(prob);
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        state = state < kNumLitStates ? 8 : 11;
+        prob = p + RepLenCoder;
+      }
+      {
+        int numBits, offset;
+        CProb *probLen = prob + LenChoice;
+        IfBit0(probLen)
+        {
+          UpdateBit0(probLen);
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          numBits = kLenNumLowBits;
+        }
+        else
+        {
+          UpdateBit1(probLen);
+          probLen = prob + LenChoice2;
+          IfBit0(probLen)
+          {
+            UpdateBit0(probLen);
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            numBits = kLenNumMidBits;
+          }
+          else
+          {
+            UpdateBit1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            numBits = kLenNumHighBits;
+          }
+        }
+        RangeDecoderBitTreeDecode(probLen, numBits, len);
+        len += offset;
+      }
+
+      if (state < 4)
+      {
+        int posSlot;
+        state += kNumLitStates;
+        prob = p + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+            kNumPosSlotBits);
+        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+          rep0 = (2 | ((UInt32)posSlot & 1));
+          if (posSlot < kEndPosModelIndex)
+          {
+            rep0 <<= numDirectBits;
+            prob = p + SpecPos + rep0 - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              RC_NORMALIZE
+              Range >>= 1;
+              rep0 <<= 1;
+              if (Code >= Range)
+              {
+                Code -= Range;
+                rep0 |= 1;
+              }
+            }
+            while (--numDirectBits != 0);
+            prob = p + Align;
+            rep0 <<= kNumAlignBits;
+            numDirectBits = kNumAlignBits;
+          }
+          {
+            int i = 1;
+            int mi = 1;
+            do
+            {
+              CProb *prob3 = prob + mi;
+              RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+              i <<= 1;
+            }
+            while(--numDirectBits != 0);
+          }
+        }
+        else
+          rep0 = posSlot;
+        if (++rep0 == (UInt32)(0))
+        {
+          /* it's for stream version */
+          len = kLzmaStreamWasFinishedId;
+          break;
+        }
+      }
+
+      len += kMatchMinLen;
+      if (rep0 > distanceLimit)
+        return LZMA_RESULT_DATA_ERROR;
+      if (dictionarySize - distanceLimit > (UInt32)len)
+        distanceLimit += len;
+      else
+        distanceLimit = dictionarySize;
+
+      do
+      {
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        previousByte = dictionary[pos];
+        dictionary[dictionaryPos] = previousByte;
+        if (++dictionaryPos == dictionarySize)
+          dictionaryPos = 0;
+        len--;
+        outStream[nowPos++] = previousByte;
+      }
+      while(len != 0 && nowPos < outSize);
+    }
+    }
+  }
+  RC_NORMALIZE;
+
+  BufferSize -= (int)(Buffer - vs->Buffer);
+  if (BufferSize < 0)
+    return LZMA_RESULT_DATA_ERROR;
+  {
+    int i;
+    for (i = 0; i < BufferSize; i++)
+      vs->Buffer[i] = Buffer[i];
+  }
+  vs->BufferSize = BufferSize;
+  vs->Range = Range;
+  vs->Code = Code;
+  vs->DictionaryPos = dictionaryPos;
+  vs->GlobalPos = (UInt32)(globalPos + nowPos);
+  vs->DistanceLimit = distanceLimit;
+  vs->Reps[0] = rep0;
+  vs->Reps[1] = rep1;
+  vs->Reps[2] = rep2;
+  vs->Reps[3] = rep3;
+  vs->State = state;
+  vs->RemainLen = len;
+  vs->TempDictionary[0] = tempDictionary[0];
+
+  (*outSizeProcessed) = nowPos;
+  return LZMA_RESULT_OK;
+}

+ 109 - 0
lzma/LzmaStateDecode.h

@@ -0,0 +1,109 @@
+/*
+  LzmaStateDecode.h
+  LZMA Decoder interface (State version)
+
+  LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this code, expressly permits you to
+  statically or dynamically link your code (or bind by name) to the
+  interfaces of this file without subjecting your linked code to the
+  terms of the CPL or GNU LGPL. Any modifications or additions
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMASTATEDECODE_H
+#define __LZMASTATEDECODE_H
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+   but memory usage will be doubled in that case */
+
+/* #define _LZMA_SYSTEM_SIZE_T */
+/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
+
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+// NOTE : Hardcoded _LZMA_SYSTEM_SIZE_T behaviour by Dennis Schridde
+#include <stddef.h>
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+  int lc;
+  int lp;
+  int pb;
+  UInt32 DictionarySize;
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp)))
+
+#define kLzmaInBufferSize 64   /* don't change it. it must be larger than kRequiredInBufferSize */
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+  CLzmaProperties Properties;
+  CProb *Probs;
+  unsigned char *Dictionary;
+
+  unsigned char Buffer[kLzmaInBufferSize];
+  int BufferSize;
+
+  UInt32 Range;
+  UInt32 Code;
+  UInt32 DictionaryPos;
+  UInt32 GlobalPos;
+  UInt32 DistanceLimit;
+  UInt32 Reps[4];
+  int State;
+  int RemainLen;  /* -2: decoder needs internal initialization
+                     -1: stream was finished,
+                      0: ok
+                    > 0: need to write RemainLen bytes as match Reps[0],
+                  */
+  unsigned char TempDictionary[4];  /* it's required when DictionarySize = 0 */
+} CLzmaDecoderState;
+
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; }
+
+/* LzmaDecode: decoding from input stream to output stream.
+  If finishDecoding != 0, then there are no more bytes in input stream
+  after inStream[inSize - 1]. */
+
+int LzmaDecode(CLzmaDecoderState *vs,
+    const unsigned char *inStream, size_t inSize,  size_t *inSizeProcessed,
+    unsigned char *outStream, size_t outSize, size_t *outSizeProcessed,
+    int finishDecoding);
+
+#endif

+ 5 - 0
lzma/Makefile.am

@@ -0,0 +1,5 @@
+if BUILD_LZMA
+noinst_LTLIBRARIES = liblzma.la
+liblzma_la_SOURCES = 7zBuffer.c 7zCrc.c 7zHeader.c 7zIn.c 7zItem.c \
+        7zMethodID.c LzmaStateDecode.c 7zDecode.c
+endif

+ 15 - 2
physfs.c

@@ -61,6 +61,11 @@ extern const PHYSFS_ArchiveInfo    __PHYSFS_ArchiveInfo_ZIP;
 extern const PHYSFS_Archiver       __PHYSFS_Archiver_ZIP;
 extern const PHYSFS_Archiver       __PHYSFS_Archiver_ZIP;
 #endif
 #endif
 
 
+#if (defined PHYSFS_SUPPORTS_LZMA)
+extern const PHYSFS_ArchiveInfo    __PHYSFS_ArchiveInfo_LZMA;
+extern const PHYSFS_Archiver       __PHYSFS_Archiver_LZMA;
+#endif
+
 #if (defined PHYSFS_SUPPORTS_GRP)
 #if (defined PHYSFS_SUPPORTS_GRP)
 extern const PHYSFS_ArchiveInfo    __PHYSFS_ArchiveInfo_GRP;
 extern const PHYSFS_ArchiveInfo    __PHYSFS_ArchiveInfo_GRP;
 extern const PHYSFS_Archiver       __PHYSFS_Archiver_GRP;
 extern const PHYSFS_Archiver       __PHYSFS_Archiver_GRP;
@@ -100,6 +105,10 @@ static const PHYSFS_ArchiveInfo *supported_types[] =
     &__PHYSFS_ArchiveInfo_ZIP,
     &__PHYSFS_ArchiveInfo_ZIP,
 #endif
 #endif
 
 
+#if (defined PHYSFS_SUPPORTS_LZMA)
+    &__PHYSFS_ArchiveInfo_LZMA,
+#endif
+
 #if (defined PHYSFS_SUPPORTS_GRP)
 #if (defined PHYSFS_SUPPORTS_GRP)
     &__PHYSFS_ArchiveInfo_GRP,
     &__PHYSFS_ArchiveInfo_GRP,
 #endif
 #endif
@@ -133,6 +142,10 @@ static const PHYSFS_Archiver *archivers[] =
     &__PHYSFS_Archiver_ZIP,
     &__PHYSFS_Archiver_ZIP,
 #endif
 #endif
 
 
+#if (defined PHYSFS_SUPPORTS_LZMA)
+    &__PHYSFS_Archiver_LZMA,
+#endif
+
 #if (defined PHYSFS_SUPPORTS_GRP)
 #if (defined PHYSFS_SUPPORTS_GRP)
     &__PHYSFS_Archiver_GRP,
     &__PHYSFS_Archiver_GRP,
 #endif
 #endif
@@ -629,7 +642,7 @@ static int freeDirHandle(DirHandle *dh, FileHandle *openList)
 
 
     for (i = openList; i != NULL; i = i->next)
     for (i = openList; i != NULL; i = i->next)
         BAIL_IF_MACRO(i->dirHandle == dh, ERR_FILES_STILL_OPEN, 0);
         BAIL_IF_MACRO(i->dirHandle == dh, ERR_FILES_STILL_OPEN, 0);
-    
+
     dh->funcs->dirClose(dh->opaque);
     dh->funcs->dirClose(dh->opaque);
     allocator.Free(dh->dirName);
     allocator.Free(dh->dirName);
     allocator.Free(dh->mountPoint);
     allocator.Free(dh->mountPoint);
@@ -1904,7 +1917,7 @@ static PHYSFS_sint64 doBufferedWrite(PHYSFS_File *handle, const void *buffer,
                                      PHYSFS_uint32 objCount)
                                      PHYSFS_uint32 objCount)
 {
 {
     FileHandle *fh = (FileHandle *) handle;
     FileHandle *fh = (FileHandle *) handle;
-    
+
     /* whole thing fits in the buffer? */
     /* whole thing fits in the buffer? */
     if (fh->buffill + (objSize * objCount) < fh->bufsize)
     if (fh->buffill + (objSize * objCount) < fh->bufsize)
     {
     {

+ 55 - 54
physfs_internal.h

@@ -56,6 +56,7 @@ extern "C" {
  #define MVL_ARCHIVE_DESCRIPTION  "Descent II Movielib format"
  #define MVL_ARCHIVE_DESCRIPTION  "Descent II Movielib format"
  #define QPAK_ARCHIVE_DESCRIPTION "Quake I/II format"
  #define QPAK_ARCHIVE_DESCRIPTION "Quake I/II format"
  #define ZIP_ARCHIVE_DESCRIPTION  "PkZip/WinZip/Info-Zip compatible"
  #define ZIP_ARCHIVE_DESCRIPTION  "PkZip/WinZip/Info-Zip compatible"
+ #define LZMA_ARCHIVE_DESCRIPTION "LZMA (7zip) format"
  #define WAD_ARCHIVE_DESCRIPTION  "DOOM engine format"
  #define WAD_ARCHIVE_DESCRIPTION  "DOOM engine format"
 
 
  #define ERR_IS_INITIALIZED       "Already initialized"
  #define ERR_IS_INITIALIZED       "Already initialized"
@@ -91,12 +92,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "Bad filename"
  #define ERR_BAD_FILENAME         "Bad filename"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS made a bad system call"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS made a bad system call"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: need dictionary"
- #define ERR_ZLIB_DATA_ERROR      "zlib: data error"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: memory error"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: buffer error"
- #define ERR_ZLIB_VERSION_ERROR   "zlib: version error"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: unknown error"
+ #define ERR_NEED_DICT            "need dictionary"
+ #define ERR_DATA_ERROR           "data error"
+ #define ERR_MEMORY_ERROR         "memory error"
+ #define ERR_BUFFER_ERROR         "buffer error"
+ #define ERR_VERSION_ERROR        "version error"
+ #define ERR_UNKNOWN_ERROR        "unknown error"
  #define ERR_SEARCHPATH_TRUNC     "Search path was truncated"
  #define ERR_SEARCHPATH_TRUNC     "Search path was truncated"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() was truncated"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() was truncated"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() had no dir"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() had no dir"
@@ -189,12 +190,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "Unzulässiger Dateiname"
  #define ERR_BAD_FILENAME         "Unzulässiger Dateiname"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS verursachte einen ungültigen Systemaufruf"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS verursachte einen ungültigen Systemaufruf"
  #define ERR_ARGV0_IS_NULL        "argv0 ist NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 ist NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: brauche Wörterbuch"
- #define ERR_ZLIB_DATA_ERROR      "zlib: Datenfehler"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: Speicherfehler"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: Bufferfehler"
- #define ERR_ZLIB_VERSION_ERROR   "zlib: Versionskonflikt"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: Unbekannter Fehler"
+ #define ERR_NEED_DICT       "brauche Wörterbuch"
+ #define ERR_DATA_ERROR      "Datenfehler"
+ #define ERR_MEMORY_ERROR    "Speicherfehler"
+ #define ERR_BUFFER_ERROR    "Bufferfehler"
+ #define ERR_VERSION_ERROR   "Versionskonflikt"
+ #define ERR_UNKNOWN_ERROR   "Unbekannter Fehler"
  #define ERR_SEARCHPATH_TRUNC     "Suchpfad war abgeschnitten"
  #define ERR_SEARCHPATH_TRUNC     "Suchpfad war abgeschnitten"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() war abgeschnitten"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() war abgeschnitten"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() bekam kein Verzeichnis"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() bekam kein Verzeichnis"
@@ -286,12 +287,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "îÅ×ÅÒÎÏÅ ÉÍÑ ÆÁÊÌÁ"
  #define ERR_BAD_FILENAME         "îÅ×ÅÒÎÏÅ ÉÍÑ ÆÁÊÌÁ"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS ×ÙÐÏÌÎÉÌÁ ÎÅ×ÅÒÎÙÊ ÓÉÓÔÅÍÎÙÊ ×ÙÚÏ×"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS ×ÙÐÏÌÎÉÌÁ ÎÅ×ÅÒÎÙÊ ÓÉÓÔÅÍÎÙÊ ×ÙÚÏ×"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: ÎÕÖÅÎ ÓÌÏ×ÁÒØ"
- #define ERR_ZLIB_DATA_ERROR      "zlib: ÏÛÉÂËÁ ÄÁÎÎÙÈ"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: ÏÛÉÂËÁ ÐÁÍÑÔÉ"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: ÏÛÉÂËÁ ÂÕÆÅÒÁ"
- #define ERR_ZLIB_VERSION_ERROR   "zlib: ÏÛÉÂËÁ ×ÅÒÓÉÉ"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: ÎÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ"
+ #define ERR_NEED_DICT       "ÎÕÖÅÎ ÓÌÏ×ÁÒØ"
+ #define ERR_DATA_ERROR      "ÏÛÉÂËÁ ÄÁÎÎÙÈ"
+ #define ERR_MEMORY_ERROR    "ÏÛÉÂËÁ ÐÁÍÑÔÉ"
+ #define ERR_BUFFER_ERROR    "ÏÛÉÂËÁ ÂÕÆÅÒÁ"
+ #define ERR_VERSION_ERROR   "ÏÛÉÂËÁ ×ÅÒÓÉÉ"
+ #define ERR_UNKNOWN_ERROR   "ÎÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ"
  #define ERR_SEARCHPATH_TRUNC     "ðÕÔØ ÐÏÉÓËÁ ÏÂÒÅÚÁÎ"
  #define ERR_SEARCHPATH_TRUNC     "ðÕÔØ ÐÏÉÓËÁ ÏÂÒÅÚÁÎ"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ÏÂÒÅÚÁÎ"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ÏÂÒÅÚÁÎ"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() ÎÅ ÐÏÌÕÞÉÌ ËÁÔÁÌÏÇ"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() ÎÅ ÐÏÌÕÞÉÌ ËÁÔÁÌÏÇ"
@@ -383,12 +384,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "Íåâåðíîå èìÿ ôàéëà"
  #define ERR_BAD_FILENAME         "Íåâåðíîå èìÿ ôàéëà"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS âûïîëíèëà íåâåðíûé ñèñòåìíûé âûçîâ"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS âûïîëíèëà íåâåðíûé ñèñòåìíûé âûçîâ"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: íóæåí ñëîâàðü"
- #define ERR_ZLIB_DATA_ERROR      "zlib: îøèáêà äàííûõ"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: îøèáêà ïàìÿòè"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: îøèáêà áóôåðà"
- #define ERR_ZLIB_VERSION_ERROR   "zlib: îøèáêà âåðñèè"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: íåèçâåñòíàÿ îøèáêà"
+ #define ERR_NEED_DICT       "íóæåí ñëîâàðü"
+ #define ERR_DATA_ERROR      "îøèáêà äàííûõ"
+ #define ERR_MEMORY_ERROR    "îøèáêà ïàìÿòè"
+ #define ERR_BUFFER_ERROR    "îøèáêà áóôåðà"
+ #define ERR_VERSION_ERROR   "îøèáêà âåðñèè"
+ #define ERR_UNKNOWN_ERROR   "íåèçâåñòíàÿ îøèáêà"
  #define ERR_SEARCHPATH_TRUNC     "Ïóòü ïîèñêà îáðåçàí"
  #define ERR_SEARCHPATH_TRUNC     "Ïóòü ïîèñêà îáðåçàí"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() îáðåçàí"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() îáðåçàí"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() íå ïîëó÷èë êàòàëîã"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() íå ïîëó÷èë êàòàëîã"
@@ -480,12 +481,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "�¥¢¥à­®¥ ¨¬ï ä ©« "
  #define ERR_BAD_FILENAME         "�¥¢¥à­®¥ ¨¬ï ä ©« "
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS ¢ë¯®«­¨«  ­¥¢¥à­ë© á¨á⥬­ë© ¢ë§®¢"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS ¢ë¯®«­¨«  ­¥¢¥à­ë© á¨á⥬­ë© ¢ë§®¢"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: ­ã¦¥­ á«®¢ àì"
- #define ERR_ZLIB_DATA_ERROR      "zlib: ®è¨¡ª  ¤ ­­ëå"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: ®è¨¡ª  ¯ ¬ïâ¨"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: ®è¨¡ª  ¡ãä¥à "
- #define ERR_ZLIB_VERSION_ERROR   "zlib: ®è¨¡ª  ¢¥àᨨ"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: ­¥¨§¢¥áâ­ ï ®è¨¡ª "
+ #define ERR_NEED_DICT       "­ã¦¥­ á«®¢ àì"
+ #define ERR_DATA_ERROR      "®è¨¡ª  ¤ ­­ëå"
+ #define ERR_MEMORY_ERROR    "®è¨¡ª  ¯ ¬ïâ¨"
+ #define ERR_BUFFER_ERROR    "®è¨¡ª  ¡ãä¥à "
+ #define ERR_VERSION_ERROR   "®è¨¡ª  ¢¥àᨨ"
+ #define ERR_UNKNOWN_ERROR   "­¥¨§¢¥áâ­ ï ®è¨¡ª "
  #define ERR_SEARCHPATH_TRUNC     "�ãâì ¯®¨áª  ®¡à¥§ ­"
  #define ERR_SEARCHPATH_TRUNC     "�ãâì ¯®¨áª  ®¡à¥§ ­"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ®¡à¥§ ­"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ®¡à¥§ ­"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() ­¥ ¯®«ã稫 ª â «®£"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() ­¥ ¯®«ã稫 ª â «®£"
@@ -577,12 +578,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "½ÕÒÕàÝÞÕ ØÜï äÐÙÛÐ"
  #define ERR_BAD_FILENAME         "½ÕÒÕàÝÞÕ ØÜï äÐÙÛÐ"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS ÒëßÞÛÝØÛÐ ÝÕÒÕàÝëÙ áØáâÕÜÝëÙ Òë×ÞÒ"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS ÒëßÞÛÝØÛÐ ÝÕÒÕàÝëÙ áØáâÕÜÝëÙ Òë×ÞÒ"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 is NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: ÝãÖÕÝ áÛÞÒÐàì"
- #define ERR_ZLIB_DATA_ERROR      "zlib: ÞèØÑÚÐ ÔÐÝÝëå"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: ÞèØÑÚÐ ßÐÜïâØ"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: ÞèØÑÚÐ ÑãäÕàÐ"
- #define ERR_ZLIB_VERSION_ERROR   "zlib: ÞèØÑÚÐ ÒÕàáØØ"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: ÝÕØ×ÒÕáâÝÐï ÞèØÑÚÐ"
+ #define ERR_NEED_DICT       "ÝãÖÕÝ áÛÞÒÐàì"
+ #define ERR_DATA_ERROR      "ÞèØÑÚÐ ÔÐÝÝëå"
+ #define ERR_MEMORY_ERROR    "ÞèØÑÚÐ ßÐÜïâØ"
+ #define ERR_BUFFER_ERROR    "ÞèØÑÚÐ ÑãäÕàÐ"
+ #define ERR_VERSION_ERROR   "ÞèØÑÚÐ ÒÕàáØØ"
+ #define ERR_UNKNOWN_ERROR   "ÝÕØ×ÒÕáâÝÐï ÞèØÑÚÐ"
  #define ERR_SEARCHPATH_TRUNC     "¿ãâì ßÞØáÚÐ ÞÑàÕ×ÐÝ"
  #define ERR_SEARCHPATH_TRUNC     "¿ãâì ßÞØáÚÐ ÞÑàÕ×ÐÝ"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ÞÑàÕ×ÐÝ"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ÞÑàÕ×ÐÝ"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() ÝÕ ßÞÛãçØÛ ÚÐâÐÛÞÓ"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() ÝÕ ßÞÛãçØÛ ÚÐâÐÛÞÓ"
@@ -676,12 +677,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "Mauvais nom de fichier"
  #define ERR_BAD_FILENAME         "Mauvais nom de fichier"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BOGUE) PhysicsFS a fait un mauvais appel système, le salaud"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BOGUE) PhysicsFS a fait un mauvais appel système, le salaud"
  #define ERR_ARGV0_IS_NULL        "argv0 est NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 est NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: a besoin du dico"
- #define ERR_ZLIB_DATA_ERROR      "zlib: erreur de données"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: erreur mémoire"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: erreur tampon"
- #define ERR_ZLIB_VERSION_ERROR   "zlib: erreur de version"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: erreur inconnue"
+ #define ERR_NEED_DICT       "a besoin du dico"
+ #define ERR_DATA_ERROR      "erreur de données"
+ #define ERR_MEMORY_ERROR    "erreur mémoire"
+ #define ERR_BUFFER_ERROR    "erreur tampon"
+ #define ERR_VERSION_ERROR   "erreur de version"
+ #define ERR_UNKNOWN_ERROR   "erreur inconnue"
  #define ERR_SEARCHPATH_TRUNC     "Le chemin de recherche a été tronqué"
  #define ERR_SEARCHPATH_TRUNC     "Le chemin de recherche a été tronqué"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() a été tronqué"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() a été tronqué"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() n'a pas de répertoire"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() n'a pas de répertoire"
@@ -774,12 +775,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "Nome de arquivo inválido"
  #define ERR_BAD_FILENAME         "Nome de arquivo inválido"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS realizou uma chamada de sistema inválida"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS realizou uma chamada de sistema inválida"
  #define ERR_ARGV0_IS_NULL        "argv0 é NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 é NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: precisa de diretório"
- #define ERR_ZLIB_DATA_ERROR      "zlib: erro nos dados"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: erro de memória"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: erro de buffer"
- #define ERR_ZLIB_VERSION_ERROR   "zlib: erro na version"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: erro desconhecido"
+ #define ERR_NEED_DICT       "precisa de diretório"
+ #define ERR_DATA_ERROR      "erro nos dados"
+ #define ERR_MEMORY_ERROR    "erro de memória"
+ #define ERR_BUFFER_ERROR    "erro de buffer"
+ #define ERR_VERSION_ERROR   "erro na version"
+ #define ERR_UNKNOWN_ERROR   "erro desconhecido"
  #define ERR_SEARCHPATH_TRUNC     "Caminho de procura quebrado"
  #define ERR_SEARCHPATH_TRUNC     "Caminho de procura quebrado"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() foi quebrado"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() foi quebrado"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() nao teve diretório"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() nao teve diretório"
@@ -871,12 +872,12 @@ extern "C" {
  #define ERR_BAD_FILENAME         "Nombre de archivo incorrecto"
  #define ERR_BAD_FILENAME         "Nombre de archivo incorrecto"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS ha hecho una llamada incorrecta al sistema"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS ha hecho una llamada incorrecta al sistema"
  #define ERR_ARGV0_IS_NULL        "argv0 es NULL"
  #define ERR_ARGV0_IS_NULL        "argv0 es NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: necesito diccionario"
- #define ERR_ZLIB_DATA_ERROR      "zlib: error de datos"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: error de memoria"
- #define ERR_ZLIB_BUFFER_ERROR    "zlib: error de buffer"
- #define ERR_ZLIB_VERSION_ERROR   "zlib: error de versión"
- #define ERR_ZLIB_UNKNOWN_ERROR   "zlib: error desconocido"
+ #define ERR_NEED_DICT       "necesito diccionario"
+ #define ERR_DATA_ERROR      "error de datos"
+ #define ERR_MEMORY_ERROR    "error de memoria"
+ #define ERR_BUFFER_ERROR    "error de buffer"
+ #define ERR_VERSION_ERROR   "error de versión"
+ #define ERR_UNKNOWN_ERROR   "error desconocido"
  #define ERR_SEARCHPATH_TRUNC     "La ruta de búsqueda ha sido truncada"
  #define ERR_SEARCHPATH_TRUNC     "La ruta de búsqueda ha sido truncada"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ha sido truncado"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ha sido truncado"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() no tenia directorio"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() no tenia directorio"