Esempio n. 1
0
        public static TrrntZipStatus ReZipFiles(List <ZippedFile> zippedFiles, ICompress originalZipFile, byte[] buffer, StatusCallback statusCallBack, LogCallback logCallback, int threadId, PauseCancel pc)
        {
            zipType inputType;

            switch (originalZipFile)
            {
            case Zip _:
                inputType = zipType.zip;
                break;

            case SevenZ _:
                inputType = zipType.sevenzip;
                break;

            case Compress.File.File _:
                inputType = zipType.file;
                break;

            default:
                return(TrrntZipStatus.Unknown);
            }

            zipType outputType = Program.OutZip == zipType.archive ? inputType : Program.OutZip;

            int bufferSize = buffer.Length;

            string filename    = originalZipFile.ZipFilename;
            string tmpFilename = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + ".tmp");

            string outExt      = outputType == zipType.zip ? ".zip" : ".7z";
            string outfilename = Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + outExt);

            if (inputType != outputType)
            {
                if (File.Exists(outfilename))
                {
                    logCallback?.Invoke(threadId, "Error output " + outExt + " file already exists");
                    return(TrrntZipStatus.RepeatFilesFound);
                }
            }

            if (File.Exists(tmpFilename))
            {
                File.Delete(tmpFilename);
            }

            ICompress zipFileOut = outputType == zipType.zip ? new Zip() : (ICompress) new SevenZ();

            try
            {
                if (outputType == zipType.zip)
                {
                    ((Zip)zipFileOut).ZipFileCreate(tmpFilename, OutputZipType.TrrntZip);
                }
                else
                {
                    zipFileOut.ZipFileCreate(tmpFilename);
                }

                ulong fileSizeTotal       = 0;
                ulong fileSizeProgress    = 0;
                int   filePercentReported = 20;
                foreach (ZippedFile f in zippedFiles)
                {
                    fileSizeTotal += f.Size;
                }

                // by now the zippedFiles have been sorted so just loop over them
                foreach (ZippedFile t in zippedFiles)
                {
                    if (Program.VerboseLogging)
                    {
                        logCallback?.Invoke(threadId, $"{t.Size,15}  {t.StringCRC}   {t.Name}");
                    }

                    Stream readStream = null;
                    ulong  streamSize = 0;

                    ZipReturn zrInput = ZipReturn.ZipUntested;

                    if (t.Size > 0)
                    {
                        switch (originalZipFile)
                        {
                        case Zip z:
                            zrInput = z.ZipFileOpenReadStream(t.Index, false, out readStream, out streamSize, out ushort _);
                            break;

                        case SevenZ z7:
                            zrInput = z7.ZipFileOpenReadStream(t.Index, out readStream, out streamSize);
                            break;

                        case Compress.File.File zf:
                            zrInput = zf.ZipFileOpenReadStream(t.Index, out readStream, out streamSize);
                            break;
                        }
                    }
                    else
                    {
                        // do nothing for a zero size file, the stream will not be used.
                        zrInput = ZipReturn.ZipGood;
                    }

                    ZipReturn zrOutput = zipFileOut.ZipFileOpenWriteStream(false, true, t.Name, streamSize, 8, out Stream writeStream);

                    if ((zrInput != ZipReturn.ZipGood) || (zrOutput != ZipReturn.ZipGood))
                    {
                        //Error writing local File.
                        zipFileOut.ZipFileCloseFailed();
                        originalZipFile.ZipFileClose();
                        File.Delete(tmpFilename);
                        return(TrrntZipStatus.CorruptZip);
                    }

                    Stream crcCs = new CrcCalculatorStream(readStream, true);

                    ulong sizetogo = streamSize;
                    while (sizetogo > 0)
                    {
                        if (pc != null)
                        {
                            pc.WaitOne();
                            if (pc.Cancelled)
                            {
                                zipFileOut.ZipFileCloseFailed();
                                originalZipFile.ZipFileClose();
                                File.Delete(tmpFilename);
                                return(TrrntZipStatus.Cancel);
                            }
                        }

                        int sizenow = sizetogo > (ulong)bufferSize ? bufferSize : (int)sizetogo;

                        fileSizeProgress += (ulong)sizenow;
                        int filePercent = (int)((double)fileSizeProgress / fileSizeTotal * 20);
                        if (filePercent != filePercentReported)
                        {
                            statusCallBack?.Invoke(threadId, filePercent * 5);
                            filePercentReported = filePercent;
                        }

                        crcCs.Read(buffer, 0, sizenow);
                        writeStream.Write(buffer, 0, sizenow);
                        sizetogo = sizetogo - (ulong)sizenow;
                    }
                    writeStream.Flush();

                    crcCs.Close();
                    if (inputType != zipType.sevenzip)
                    {
                        originalZipFile.ZipFileCloseReadStream();
                    }

                    uint crc = (uint)((CrcCalculatorStream)crcCs).Crc;

                    if (t.CRC == null)
                    {
                        t.CRC = crc;
                    }

                    if (crc != t.CRC)
                    {
                        zipFileOut.ZipFileCloseFailed();
                        originalZipFile.ZipFileClose();
                        File.Delete(tmpFilename);
                        return(TrrntZipStatus.CorruptZip);
                    }

                    zipFileOut.ZipFileCloseWriteStream(t.ByteCRC);
                }
                statusCallBack?.Invoke(threadId, 100);

                zipFileOut.ZipFileClose();
                originalZipFile.ZipFileClose();
                File.Delete(filename);
                File.Move(tmpFilename, outfilename);

                return(TrrntZipStatus.Trrntzipped);
            }
            catch (Exception)
            {
                zipFileOut?.ZipFileCloseFailed();
                originalZipFile?.ZipFileClose();
                return(TrrntZipStatus.CorruptZip);
            }
        }
Esempio n. 2
0
        public TrrntZipStatus Process(FileInfo fi, PauseCancel pc = null)
        {
            if (Program.VerboseLogging)
            {
                StatusLogCallBack?.Invoke(ThreadId, "");
            }

            StatusLogCallBack?.Invoke(ThreadId, fi.Name + " - ");

            // First open the zip (7z) file, and fail out if it is corrupt.
            TrrntZipStatus tzs = OpenZip(fi, out ICompress zipFile);

            // this will return ValidTrrntZip or CorruptZip.

            for (int i = 0; i < zipFile.LocalFilesCount(); i++)
            {
                LocalFile lf = zipFile.GetLocalFile(i);
                Debug.WriteLine("Name = " + lf.Filename + " , " + lf.UncompressedSize);
            }

            if ((tzs & TrrntZipStatus.CorruptZip) == TrrntZipStatus.CorruptZip)
            {
                StatusLogCallBack?.Invoke(ThreadId, "Zip file is corrupt");
                return(TrrntZipStatus.CorruptZip);
            }


            // the zip file may have found a valid trrntzip header, but we now check that all the file info
            // is actually valid, and may invalidate it being a valid trrntzip if any problem is found.

            List <ZippedFile> zippedFiles = ReadZipContent(zipFile);

            zipType localOutputType = Program.OutZip;

            // check if the compression type has changed
            zipType inputType;

            switch (zipFile)
            {
            case Zip _:
                tzs      |= TorrentZipCheck.CheckZipFiles(ref zippedFiles, ThreadId, StatusLogCallBack);
                inputType = zipType.zip;
                break;

            case SevenZ _:
                tzs      |= TorrentZipCheck.CheckSevenZipFiles(ref zippedFiles, ThreadId, StatusLogCallBack);
                inputType = zipType.sevenzip;
                break;

            case Compress.File.File _:
                inputType = zipType.file;
                if (localOutputType == zipType.archive)
                {
                    localOutputType = zipType.zip;
                }
                break;

            default:
                return(TrrntZipStatus.Unknown);
            }
            zipType outputType = localOutputType == zipType.archive ? inputType : Program.OutZip;

            bool compressionChanged = inputType != outputType;


            // if tza is now just 'ValidTrrntzip' the it is fully valid, and nothing needs to be done to it.

            if (((tzs == TrrntZipStatus.ValidTrrntzip) && !compressionChanged && !Program.ForceReZip) || Program.CheckOnly)
            {
                StatusLogCallBack?.Invoke(ThreadId, "Skipping File");
                zipFile.ZipFileClose();
                return(tzs);
            }

            // if compressionChanged then the required file order will also have changed to need to re-sort the files.
            if (compressionChanged)
            {
                switch (outputType)
                {
                case zipType.zip:
                    tzs |= TorrentZipCheck.CheckZipFiles(ref zippedFiles, ThreadId, StatusLogCallBack);
                    break;

                case zipType.sevenzip:
                    tzs |= TorrentZipCheck.CheckSevenZipFiles(ref zippedFiles, ThreadId, StatusLogCallBack);
                    break;
                }
            }

            StatusLogCallBack?.Invoke(ThreadId, "TorrentZipping");
            TrrntZipStatus fixedTzs = TorrentZipRebuild.ReZipFiles(zippedFiles, zipFile, _buffer, StatusCallBack, StatusLogCallBack, ThreadId, pc);

            return(fixedTzs);
        }