Esempio n. 1
0
        public static TrrntZipStatus ReZipFiles(List <ZippedFile> zippedFiles, ICompress originalZipFile, byte[] buffer, StatusCallback StatusCallBack, LogCallback LogCallback, int ThreadID)
        {
            int bufferSize = buffer.Length;

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

            string outfilename = Path.GetDirectoryName(filename) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(filename) + ".zip";

            if (Path.GetExtension(filename) == ".7z")
            {
                if (File.Exists(outfilename))
                {
                    LogCallback?.Invoke(ThreadID, "Error output .zip file already exists");
                    return(TrrntZipStatus.RepeatFilesFound);
                }
            }

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

            ICompress zipFileOut = new ZipFile();

            try
            {
                zipFileOut.ZipFileCreate(tmpFilename);

                // by now the zippedFiles have been sorted so just loop over them
                for (int i = 0; i < zippedFiles.Count; i++)
                {
                    StatusCallBack?.Invoke(ThreadID, (int)((double)(i + 1) / (zippedFiles.Count) * 100));

                    ZippedFile t = zippedFiles[i];

                    if (Program.VerboseLogging)
                    {
                        LogCallback?.Invoke(ThreadID, $"{t.Size,15}  {t.StringCRC}   {t.Name}");
                    }

                    Stream readStream = null;
                    ulong  streamSize = 0;
                    ushort compMethod;

                    ZipFile   z       = originalZipFile as ZipFile;
                    ZipReturn zrInput = ZipReturn.ZipUntested;
                    if (z != null)
                    {
                        zrInput = z.ZipFileOpenReadStream(t.Index, false, out readStream, out streamSize, out compMethod);
                    }
                    SevenZ z7 = originalZipFile as SevenZ;
                    if (z7 != null)
                    {
                        zrInput = z7.ZipFileOpenReadStream(t.Index, out readStream, out streamSize);
                    }

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

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

                    Stream crcCs = new CrcCalculatorStream(readStream, true);

                    ulong sizetogo = streamSize;
                    while (sizetogo > 0)
                    {
                        int sizenow = sizetogo > (ulong)bufferSize ? bufferSize : (int)sizetogo;

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

                    crcCs.Close();
                    if (z != null)
                    {
                        originalZipFile.ZipFileCloseReadStream();
                    }

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

                    if (crc != t.CRC)
                    {
                        return(TrrntZipStatus.CorruptZip);
                    }

                    zipFileOut.ZipFileCloseWriteStream(t.ByteCRC);
                }

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

                return(TrrntZipStatus.ValidTrrntzip);
            }
            catch (Exception)
            {
                zipFileOut?.ZipFileCloseFailed();
                originalZipFile?.ZipFileClose();
                return(TrrntZipStatus.CorruptZip);
            }
        }
Esempio n. 2
0
        public static TrrntZipStatus CheckZipFiles(ref List <ZippedFile> zippedFiles)
        {
            TrrntZipStatus tzStatus = TrrntZipStatus.Unknown;


            // ***************************** RULE 1 *************************************
            // Directory separator should be a '/' a '\' is invalid and should be replaced with '/'
            //
            // check if any '\' = 92 need converted to '/' = 47
            // this needs done before the sort, so that the sort is correct.
            // return BadDirectorySeparator if errors found.
            bool error1 = false;

            foreach (ZippedFile t in zippedFiles)
            {
                char[] bytes  = t.Name.ToCharArray();
                bool   fixDir = false;
                for (int j = 0; j < bytes.Length; j++)
                {
                    if (bytes[j] != 92)
                    {
                        continue;
                    }
                    fixDir    = true;
                    bytes[j]  = (char)47;
                    tzStatus |= TrrntZipStatus.BadDirectorySeparator;
                    if (!error1 && Program.VerboseLogging)
                    {
                        error1 = true;
                        Console.WriteLine("Incorrect directory separator found");
                    }
                }
                if (fixDir)
                {
                    t.Name = new string(bytes);
                }
            }


            // ***************************** RULE 2 *************************************
            // All Files in a torrentzip should be sorted with a lower case file compare.
            //
            // if needed sort the files correctly, and return Unsorted if errors found.
            bool error2        = false;
            bool thisSortFound = true;

            while (thisSortFound)
            {
                thisSortFound = false;
                for (int i = 0; i < zippedFiles.Count - 1; i++)
                {
                    int c = TrrntZipStringCompare(zippedFiles[i].Name, zippedFiles[i + 1].Name);
                    if (c > 0)
                    {
                        ZippedFile T = zippedFiles[i];
                        zippedFiles[i]     = zippedFiles[i + 1];
                        zippedFiles[i + 1] = T;

                        tzStatus     |= TrrntZipStatus.Unsorted;
                        thisSortFound = true;
                        if (!error2 && Program.VerboseLogging)
                        {
                            error2 = true;
                            Console.WriteLine("Incorrect file order found");
                        }
                    }
                }
            }


            // ***************************** RULE 3 *************************************
            // Directory marker files are only needed if they are empty directories.
            //
            // now that the files are sorted correctly, we can see if there are unneeded
            // directory files, by first finding directory files (these end in a '\' character ascii 92)
            // and then checking if the next file is a file in that found directory.
            // If we find this 2 entry pattern (directory followed by file in that directory)
            // then the directory entry should not be present and the torrentzip is incorrect.
            // return ExtraDirectoryEnteries if error is found.
            bool error3 = false;

            for (int i = 0; i < zippedFiles.Count - 1; i++)
            {
                // check if this is a directory entry
                if (zippedFiles[i].Name[zippedFiles[i].Name.Length - 1] != 47)
                {
                    continue;
                }

                // check if the next filename is shorter or equal to this filename.
                // if it is shorter or equal it cannot be a file in the directory.
                if (zippedFiles[i + 1].Name.Length <= zippedFiles[i].Name.Length)
                {
                    continue;
                }

                // check if the directory part of the two file enteries match
                // if they do we found an incorrect directory entry.
                bool delete = true;
                for (int j = 0; j < zippedFiles[i].Name.Length; j++)
                {
                    if (zippedFiles[i].Name[j] != zippedFiles[i + 1].Name[j])
                    {
                        delete = false;
                        break;
                    }
                }

                // we found an incorrect directory so remove it.
                if (delete)
                {
                    zippedFiles.RemoveAt(i);
                    tzStatus |= TrrntZipStatus.ExtraDirectoryEnteries;
                    if (!error3 && Program.VerboseLogging)
                    {
                        error3 = true;
                        Console.WriteLine("Un-needed directory records found");
                    }

                    i--;
                }
            }


            // check for repeat files
            bool error4 = false;

            for (int i = 0; i < zippedFiles.Count - 1; i++)
            {
                if (zippedFiles[i].Name == zippedFiles[i + 1].Name)
                {
                    tzStatus |= TrrntZipStatus.RepeatFilesFound;
                    if (!error4 && Program.VerboseLogging)
                    {
                        error4 = true;
                        Console.WriteLine("Duplcate file enteries found");
                    }
                }
            }

            return(tzStatus);
        }