7zip support, written by Dennis Schridde, and heavily Ryanified by me.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 11 Apr 2006 14:33:48 +0000
changeset 774 916c2e81e77f
parent 773 8215379394b5
child 775 a8cc6b8a8e9c
7zip support, written by Dennis Schridde, and heavily Ryanified by me.
CHANGELOG
Makefile.am.newautomake
archivers/Makefile.am
archivers/lzma.c
configure.in
lzma/7zBuffer.c
lzma/7zBuffer.h
lzma/7zCrc.c
lzma/7zCrc.h
lzma/7zDecode.c
lzma/7zDecode.h
lzma/7zHeader.c
lzma/7zHeader.h
lzma/7zIn.c
lzma/7zIn.h
lzma/7zItem.c
lzma/7zItem.h
lzma/7zMethodID.c
lzma/7zMethodID.h
lzma/7zTypes.h
lzma/LZMA-LICENSE.txt
lzma/LzmaStateDecode.c
lzma/LzmaStateDecode.h
lzma/Makefile.am
physfs.c
physfs_internal.h
--- a/CHANGELOG	Thu Mar 23 10:19:55 2006 +0000
+++ b/CHANGELOG	Tue Apr 11 14:33:48 2006 +0000
@@ -2,6 +2,7 @@
  * CHANGELOG.
  */
 
+04112006 - Added LZMA archiver...7zip support (thanks, Dennis!).
 03232006 - Added -fvisibility for gcc4 (http://gcc.gnu.org/wiki/Visibility)
 01012006 - Cleaned up overflow checks in platform memory allocators (thanks to
            Nicolas Lebedenco for pointing out the original issue with
--- a/Makefile.am.newautomake	Thu Mar 23 10:19:55 2006 +0000
+++ b/Makefile.am.newautomake	Tue Apr 11 14:33:48 2006 +0000
@@ -105,7 +105,7 @@
 
 else
 
-SUBDIRS = platform archivers zlib123 . test extras
+SUBDIRS = platform archivers zlib123 lzma . test extras
 
 libphysfs_la_SOURCES =	\
 	physfs.c	\
@@ -118,13 +118,20 @@
 ZLIB_LIB =
 endif
 
+if BUILD_LZMA
+LZMA_LIB = lzma/liblzma.la
+else
+LZMA_LIB =
+endif
+
 libphysfs_la_LDFLAGS = 		\
 	-release $(LT_RELEASE)	\
 	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 libphysfs_la_LIBADD =	\
 	archivers/libarchivers.la	\
 	platform/libplatform.la	\
-	$(ZLIB_LIB)
+	$(ZLIB_LIB) \
+	$(LZMA_LIB)
 
 EXTRA_DIST =	\
 	CREDITS \
--- a/archivers/Makefile.am	Thu Mar 23 10:19:55 2006 +0000
+++ b/archivers/Makefile.am	Tue Apr 11 14:33:48 2006 +0000
@@ -1,9 +1,13 @@
 noinst_LTLIBRARIES = libarchivers.la
 
+INCLUDES = -I$(top_srcdir)
+
 if BUILD_ZLIB
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/zlib123
-else
-INCLUDES = -I$(top_srcdir)
+INCLUDES += -I$(top_srcdir)/zlib123
+endif
+
+if BUILD_LZMA
+INCLUDES += -I$(top_srcdir)/lzma
 endif
 
 libarchivers_la_SOURCES =	\
@@ -13,5 +17,6 @@
 	hog.c		\
 	mvl.c		\
 	zip.c		\
+	lzma.c		\
 	qpak.c		\
 	mix.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/archivers/lzma.c	Tue Apr 11 14:33:48 2006 +0000
@@ -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 ... */
+
--- a/configure.in	Thu Mar 23 10:19:55 2006 +0000
+++ b/configure.in	Tue Apr 11 14:33:48 2006 +0000
@@ -139,6 +139,18 @@
 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...
 AC_ARG_ENABLE(grp,
 [  --enable-grp               enable Build Engine GRP support [default=yes]],
@@ -564,6 +576,7 @@
 
 dnl Add Makefile conditionals
 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_MACOSX, test x$this_is_macosx = xyes)
 AM_CONDITIONAL(BUILD_BEOS, test x$this_is_beos = xyes)
@@ -575,6 +588,7 @@
 archivers/Makefile
 platform/Makefile
 zlib123/Makefile
+lzma/Makefile
 test/Makefile
 extras/Makefile
 physfs.spec
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zBuffer.c	Tue Apr 11 14:33:48 2006 +0000
@@ -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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zBuffer.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zCrc.c	Tue Apr 11 14:33:48 2006 +0000
@@ -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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zCrc.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zDecode.c	Tue Apr 11 14:33:48 2006 +0000
@@ -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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zDecode.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zHeader.c	Tue Apr 11 14:33:48 2006 +0000
@@ -0,0 +1,5 @@
+/*  7zHeader.c */
+
+#include "7zHeader.h"
+
+Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zHeader.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zIn.c	Tue Apr 11 14:33:48 2006 +0000
@@ -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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zIn.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zItem.c	Tue Apr 11 14:33:48 2006 +0000
@@ -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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zItem.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zMethodID.c	Tue Apr 11 14:33:48 2006 +0000
@@ -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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zMethodID.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/7zTypes.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/LZMA-LICENSE.txt	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/LzmaStateDecode.c	Tue Apr 11 14:33:48 2006 +0000
@@ -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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/LzmaStateDecode.h	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lzma/Makefile.am	Tue Apr 11 14:33:48 2006 +0000
@@ -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
--- a/physfs.c	Thu Mar 23 10:19:55 2006 +0000
+++ b/physfs.c	Tue Apr 11 14:33:48 2006 +0000
@@ -61,6 +61,11 @@
 extern const PHYSFS_Archiver       __PHYSFS_Archiver_ZIP;
 #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)
 extern const PHYSFS_ArchiveInfo    __PHYSFS_ArchiveInfo_GRP;
 extern const PHYSFS_Archiver       __PHYSFS_Archiver_GRP;
@@ -100,6 +105,10 @@
     &__PHYSFS_ArchiveInfo_ZIP,
 #endif
 
+#if (defined PHYSFS_SUPPORTS_LZMA)
+    &__PHYSFS_ArchiveInfo_LZMA,
+#endif
+
 #if (defined PHYSFS_SUPPORTS_GRP)
     &__PHYSFS_ArchiveInfo_GRP,
 #endif
@@ -133,6 +142,10 @@
     &__PHYSFS_Archiver_ZIP,
 #endif
 
+#if (defined PHYSFS_SUPPORTS_LZMA)
+    &__PHYSFS_Archiver_LZMA,
+#endif
+
 #if (defined PHYSFS_SUPPORTS_GRP)
     &__PHYSFS_Archiver_GRP,
 #endif
@@ -629,7 +642,7 @@
 
     for (i = openList; i != NULL; i = i->next)
         BAIL_IF_MACRO(i->dirHandle == dh, ERR_FILES_STILL_OPEN, 0);
-    
+
     dh->funcs->dirClose(dh->opaque);
     allocator.Free(dh->dirName);
     allocator.Free(dh->mountPoint);
@@ -1904,7 +1917,7 @@
                                      PHYSFS_uint32 objCount)
 {
     FileHandle *fh = (FileHandle *) handle;
-    
+
     /* whole thing fits in the buffer? */
     if (fh->buffill + (objSize * objCount) < fh->bufsize)
     {
--- a/physfs_internal.h	Thu Mar 23 10:19:55 2006 +0000
+++ b/physfs_internal.h	Tue Apr 11 14:33:48 2006 +0000
@@ -56,6 +56,7 @@
  #define MVL_ARCHIVE_DESCRIPTION  "Descent II Movielib format"
  #define QPAK_ARCHIVE_DESCRIPTION "Quake I/II format"
  #define ZIP_ARCHIVE_DESCRIPTION  "PkZip/WinZip/Info-Zip compatible"
+ #define LZMA_ARCHIVE_DESCRIPTION "LZMA (7zip) format"
  #define WAD_ARCHIVE_DESCRIPTION  "DOOM engine format"
 
  #define ERR_IS_INITIALIZED       "Already initialized"
@@ -91,12 +92,12 @@
  #define ERR_BAD_FILENAME         "Bad filename"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS made a bad system call"
  #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_GETMODFN_TRUNC       "GetModuleFileName() was truncated"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() had no dir"
@@ -189,12 +190,12 @@
  #define ERR_BAD_FILENAME         "Unzulssiger Dateiname"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS verursachte einen ungltigen Systemaufruf"
  #define ERR_ARGV0_IS_NULL        "argv0 ist NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: brauche Wrterbuch"
- #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 Wrterbuch"
+ #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_GETMODFN_TRUNC       "GetModuleFileName() war abgeschnitten"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() bekam kein Verzeichnis"
@@ -286,12 +287,12 @@
  #define ERR_BAD_FILENAME         "  "
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS    "
  #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_GETMODFN_TRUNC       "GetModuleFileName() "
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName()   "
@@ -383,12 +384,12 @@
  #define ERR_BAD_FILENAME         "  "
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS    "
  #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_GETMODFN_TRUNC       "GetModuleFileName() "
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName()   "
@@ -480,12 +481,12 @@
  #define ERR_BAD_FILENAME         "୮  䠩"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS 믮  ⥬ 맮"
  #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_GETMODFN_TRUNC       "GetModuleFileName() १"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName()  稫 ⠫"
@@ -577,12 +578,12 @@
  #define ERR_BAD_FILENAME         "  "
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS    "
  #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_GETMODFN_TRUNC       "GetModuleFileName() "
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName()   "
@@ -676,12 +677,12 @@
  #define ERR_BAD_FILENAME         "Mauvais nom de fichier"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BOGUE) PhysicsFS a fait un mauvais appel systme, le salaud"
  #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 donnes"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: erreur mmoire"
- #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 donnes"
+ #define ERR_MEMORY_ERROR    "erreur mmoire"
+ #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_GETMODFN_TRUNC       "GetModuleFileName() a t tronqu"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() n'a pas de rpertoire"
@@ -774,12 +775,12 @@
  #define ERR_BAD_FILENAME         "Nome de arquivo invlido"
  #define ERR_PHYSFS_BAD_OS_CALL   "(BUG) PhysicsFS realizou uma chamada de sistema invlida"
  #define ERR_ARGV0_IS_NULL        "argv0  NULL"
- #define ERR_ZLIB_NEED_DICT       "zlib: precisa de diretrio"
- #define ERR_ZLIB_DATA_ERROR      "zlib: erro nos dados"
- #define ERR_ZLIB_MEMORY_ERROR    "zlib: erro de memria"
- #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 diretrio"
+ #define ERR_DATA_ERROR      "erro nos dados"
+ #define ERR_MEMORY_ERROR    "erro de memria"
+ #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_GETMODFN_TRUNC       "GetModuleFileName() foi quebrado"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() nao teve diretrio"
@@ -871,12 +872,12 @@
  #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_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 versin"
- #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 versin"
+ #define ERR_UNKNOWN_ERROR   "error desconocido"
  #define ERR_SEARCHPATH_TRUNC     "La ruta de bsqueda ha sido truncada"
  #define ERR_GETMODFN_TRUNC       "GetModuleFileName() ha sido truncado"
  #define ERR_GETMODFN_NO_DIR      "GetModuleFileName() no tenia directorio"