public static string DecompressLZMA(byte[] compressedFile)
        {
            IntPtr intPtr = new IntPtr(compressedFile.Length - 13);

            byte[] array        = new byte[intPtr.ToInt64()];
            IntPtr outPropsSize = new IntPtr(5);

            byte[] array2 = new byte[5];
            compressedFile.CopyTo(array, 13);
            for (int i = 0; i < 5; i++)
            {
                array2[i] = compressedFile[i];
            }
            int num = 0;

            for (int j = 0; j < 8; j++)
            {
                num += (int)compressedFile[j + 5] << 8 * j;
            }
            IntPtr intPtr2 = new IntPtr(num);

            byte[] array3 = new byte[num];
            int    num2   = LZMA.LzmaUncompress(array3, ref intPtr2, array, ref intPtr, array2, outPropsSize);

            if (num2 != 0)
            {
                MessageBox.Show("Decompression returned " + num2);
            }
            return(new string(Encoding.UTF8.GetString(array3).ToCharArray()));
        }
Beispiel #2
0
        // Extract a LZMA-compressed file.
        private async Task HandleCompressedFile(SFileInfo fileInfo, BinaryReader binaryReader, string sectionUrl)
        {
//            Console.WriteLine($"[FILE-{fileInfo.Section} {fileInfo.FullPath}]: handling compressed file");

            // A multipart file can span multiple sections,
            // so we have to keep track of how much has been read.
            // This code is kind of irritating and semi-confusing, but it works.
            if (binaryReader.BaseStream.Position + fileInfo.CompressedLength > binaryReader.BaseStream.Length)
            {
//                Console.WriteLine(
//                    $"    Multi-part file detected @ 0x{binaryReader.BaseStream.Position:X8} (total {fileInfo.CompressedLength}, reader has {binaryReader.BaseStream.Length - binaryReader.BaseStream.Position})");

                var bytesRead    = 0;
                var maxBytesRead = fileInfo.CompressedLength - 13; // header is 13 bytes
                var curSection   = fileInfo.Section;

                var props = binaryReader.ReadBytes(5);
                binaryReader.BaseStream.Seek(8, SeekOrigin.Current);

                // Here we're reading fragments until we've got everything.
                // First we read as much data from the current section as we can.
                var bytes          = new List <byte>();
                var readFromMaster = (int)(binaryReader.BaseStream.Length - binaryReader.BaseStream.Position);

                bytes.AddRange(binaryReader.ReadBytes(readFromMaster));
                bytesRead += readFromMaster;

                // Then, we continuously jump to the next section, until all the data is retrieved.
                while (bytesRead < maxBytesRead)
                {
                    // Create a new section URL that gives us access to the next section.
                    var newSectUrl = sectionUrl.Replace($"section{fileInfo.Section}",
                                                        $"section{++curSection}");
                    // Fetch a BinaryReader for the new section.
                    var newSectReader = await FetchSection(newSectUrl);

                    // Calculate the remaining number of bytes to read.
                    // This takes into account the length of the section as opposed to the total length of the file.
                    var bytesToRead = (int)Math.Min(newSectReader.BaseStream.Length,
                                                    maxBytesRead - bytes.Count);
                    bytes.AddRange(newSectReader.ReadBytes(bytesToRead));
                    bytesRead += bytesToRead;
                }

                var destLen = new IntPtr(fileInfo.Length);
                var srcLen  = new IntPtr(fileInfo.CompressedLength - 13);

                var inData = bytes.ToArray();
                bytes.Clear();
                var decompressedOutput = new byte[destLen.ToInt32()];

                LZMA.LzmaUncompress(decompressedOutput, ref destLen, inData,
                                    ref srcLen, props,
                                    _propsSizePtr);

                using (var outStream = new FileStream(fileInfo.FullPath, FileMode.Create))
                {
                    outStream.Write(decompressedOutput, 0, decompressedOutput.Length);
                }

                decompressedOutput = null;
                props  = null;
                inData = null;
            }
            else
            {
                // Thankfully there are some files that are small and don't require reading multiple sections at a time.

                var destLen = new IntPtr(fileInfo.Length);
                var srcLen  = new IntPtr(fileInfo.CompressedLength - 13);

                var props = binaryReader.ReadBytes(5);
                binaryReader.BaseStream.Seek(8, SeekOrigin.Current);

                var bytes = new byte[fileInfo.CompressedLength];

                binaryReader.Read(bytes, 0, bytes.Length);

                var decompressedOutput = new byte[destLen.ToInt32()];

                LZMA.LzmaUncompress(decompressedOutput, ref destLen, bytes,
                                    ref srcLen, props,
                                    _propsSizePtr);

                using (var outStream = new FileStream(fileInfo.FullPath, FileMode.Create))
                {
                    outStream.Write(decompressedOutput, 0, decompressedOutput.Length);
                }

                bytes = null;
                decompressedOutput = null;
                props = null;
            }
        }
Beispiel #3
0
        public void LzmaUncompress(SharedSettings s)
        {
            switch (s.Variant)
            {
            case 1:
            {
                var decoder = new LZMA.CLzmaDec();
                decoder.LzmaDec_Construct();

                var res = decoder.LzmaDec_Allocate(P.From(s.Enc), checked ((uint)s.Enc.Length), LZMA.ISzAlloc.SmallAlloc);
                if (res != LZMA.SZ_OK)
                {
                    throw new Exception("Allocate failed: " + res);
                }

                decoder.LzmaDec_Init();

                P <byte> dstPtr        = P.From(s.Dst);
                long     s_WrittenSize = s.Dst.Length;
                s.WrittenSize = 0;

                P <byte> srcPtr     = P.From(s.Src);
                long     s_UsedSize = s.Src.Length;
                s.UsedSize = 0;

                for (;;)
                {
                    LZMA.ELzmaStatus status;
                    res = decoder.LzmaDec_DecodeToBuf(dstPtr, ref s_WrittenSize, srcPtr, ref s_UsedSize, LZMA.ELzmaFinishMode.LZMA_FINISH_END, out status);
                    if (res != LZMA.SZ_OK)
                    {
                        throw new Exception("DecodeToBuf failed: " + res);
                    }

                    s.WrittenSize += checked ((int)s_WrittenSize);
                    s.UsedSize    += checked ((int)s_UsedSize);
                    dstPtr        += s_WrittenSize;
                    srcPtr        += s_UsedSize;
                    s_WrittenSize  = dstPtr.mBuffer.Length - dstPtr.mOffset;
                    s_UsedSize     = srcPtr.mBuffer.Length - srcPtr.mOffset;

                    if (status == LZMA.ELzmaStatus.LZMA_STATUS_NEEDS_MORE_INPUT ||
                        status == LZMA.ELzmaStatus.LZMA_STATUS_NOT_FINISHED)
                    {
                        continue;
                    }

                    if (status == LZMA.ELzmaStatus.LZMA_STATUS_FINISHED_WITH_MARK)
                    {
                        if (s.ActualWriteEndMark == 0)
                        {
                            throw new Exception("Finished with mark even though we didn't want to write one.");
                        }
                        break;
                    }

                    if (status == LZMA.ELzmaStatus.LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
                    {
                        if (s.ActualWriteEndMark != 0)
                        {
                            break;
                        }
                    }

                    throw new NotSupportedException("Unsupported status case: " + status);
                }

                decoder.LzmaDec_Free(LZMA.ISzAlloc.SmallAlloc);

                s.WrittenSize = (int)dstPtr.mOffset;
                s.UsedSize    = (int)srcPtr.mOffset;
            }
            break;

            default:
            {
                long s_WrittenSize = s.Dst.Length;
                long s_UsedSize    = s.Src.Length;
                var  res           = LZMA.LzmaUncompress(
                    P.From(s.Dst), ref s_WrittenSize,
                    P.From(s.Src), ref s_UsedSize,
                    P.From(s.Enc), s.Enc.Length);
                if (res != LZMA.SZ_OK)
                {
                    throw new Exception("LzmaUcompress failed: " + res);
                }
                s.WrittenSize = (int)s_WrittenSize;
                s.UsedSize    = (int)s_UsedSize;
            }
            break;
            }
        }