// find fix files, if the gotFile has been fully scanned check the SHA1/MD5, if not then just return true as the CRC/Size is all we have to go on.
        // this means that if the gotfile has not been fully scanned this will return true even with the source and destination SHA1/MD5 possibly different.
        public static bool CheckIfMissingFileCanBeFixedByGotFile(RvFile missingFile, RvFile gotFile)
        {
            if (missingFile.FileStatusIs(FileStatus.SHA1FromDAT) &&  gotFile.FileStatusIs(FileStatus.SHA1Verified) && !ArrByte.bCompare(missingFile.SHA1, gotFile.SHA1))
                return false;
            if (missingFile.FileStatusIs(FileStatus.MD5FromDAT) &&  gotFile.FileStatusIs(FileStatus.MD5Verified) && !ArrByte.bCompare(missingFile.MD5, gotFile.MD5))
                return false;

            return true;
        }
        public static void LogOut(RvFile f)
        {
            if (!Settings.DebugLogsEnabled) return;

            StreamWriter sw = new StreamWriter(_logfilename, true);
            ReportFile(sw, f);
            sw.Flush();
            sw.Close();
        }
        private static void LoadDiskFromDat(ref RvDir tGame, XmlNode romNode)
        {
            if (romNode.Attributes == null)
                return;

            XmlNode name = romNode.Attributes.GetNamedItem("name");
            RvFile tRom = new RvFile(FileType.File)
            {
                Name = VarFix.CleanFullFileName(name) + ".chd",
                SHA1CHD = VarFix.CleanMD5SHA1(romNode.Attributes.GetNamedItem("sha1"), 40),
                Status = VarFix.ToLower(romNode.Attributes.GetNamedItem("status")),

                Dat = tGame.Dat
            };

            if (tRom.SHA1CHD != null) tRom.FileStatusSet(FileStatus.SHA1CHDFromDAT);

            tGame.ChildAdd(tRom);
        }
        // find all of the files that we think we have that match the needed CRC and Size.
        public static void RomSearchFindFixes(RvFile tRom, List<RvFile> lstFiles, out List<RvFile> lstFilesOut)
        {
            lstFilesOut = new List<RvFile>();
            if (tRom.CRC == null || tRom.Size == null)
                return;

            int intIndex;
            int intRes = RomSearchCRCSize(tRom, lstFiles, out intIndex);

            while (intRes == 0)
            {
                if (lstFiles[intIndex].GotStatus == GotStatus.Got && FindFixes.CheckIfMissingFileCanBeFixedByGotFile(tRom, lstFiles[intIndex]))
                    lstFilesOut.Add(lstFiles[intIndex]);

                intIndex++;
                intRes = intIndex < lstFiles.Count ? RomSortCRCSizeFunc(lstFiles[intIndex], tRom) : 1;
            }
        }
        // This Function returns:
        // Good            : Everything Worked Correctly
        // RescanNeeded     : Something unexpectidly changed in the files, so Stop prompt user to rescan.
        // LogicError       : This Should never happen and is a logic problem in the code
        // FileSystemError  : Something is wrong with the files
        /// <summary>
        /// Performs the ROMVault File Copy, with the source and destination being files or zipped files
        /// </summary>
        /// <param name="fileIn">This is the file being copied, it may be a zipped file or a regular file system file</param>
        /// <param name="zipFileOut">This is the zip file that is being writen to, if it is null a new zip file will be made if we are coping to a zip</param>
        /// <param name="zipFilenameOut">This is the name of the .zip file to be made that will be created in zipFileOut</param>
        /// <param name="fileOut">This is the actual output filename</param>
        /// <param name="forceRaw">if true then we will do a raw copy, this is so that we can copy corrupt zips</param>
        /// <param name="error">This is the returned error message if this copy fails</param>
        /// <param name="foundFile">If we are SHA1/MD5 checking the source file for the first time, and it is different from what we expected the correct values for this file are returned in foundFile</param>
        /// <returns>ReturnCode.Good is the valid return code otherwire we have an error</returns>
        public static ReturnCode CopyFile(RvFile fileIn, ref ZipFile zipFileOut, string zipFilenameOut, RvFile fileOut, bool forceRaw, out string error, out RvFile foundFile)
        {
            foundFile = null;
            error = "";

            if (_buffer == null)
                _buffer = new byte[BufferSize];

            bool rawCopy = RawCopy(fileIn, fileOut, forceRaw);

            ulong streamSize = 0;
            ushort compressionMethod = 8;
            bool sourceTrrntzip = false;

            ZipFile zipFileIn = null;
            System.IO.Stream readStream = null;

            bool isZeroLengthFile = DBHelper.IsZeroLengthFile(fileOut);
            if (!isZeroLengthFile)
            {
                #region check that the in and out file match
                if (fileOut.FileStatusIs(FileStatus.SizeFromDAT) && fileOut.Size != null && fileIn.Size != fileOut.Size)
                {
                    error = "Source and destination Size does not match. Logic Error.";
                    return ReturnCode.LogicError;
                }
                if (fileOut.FileStatusIs(FileStatus.CRCFromDAT) && fileOut.CRC != null && !ArrByte.bCompare(fileIn.CRC, fileOut.CRC))
                {
                    error = "Source and destination CRC does not match. Logic Error.";
                    return ReturnCode.LogicError;
                }

                if (fileOut.FileStatusIs(FileStatus.SHA1FromDAT) && fileIn.FileStatusIs(FileStatus.SHA1Verified))
                {
                    if (fileIn.SHA1 != null && fileOut.SHA1 != null && !ArrByte.bCompare(fileIn.SHA1, fileOut.SHA1))
                    {
                        error = "Source and destination SHA1 does not match. Logic Error.";
                        return ReturnCode.LogicError;
                    }
                }
                if (fileOut.FileStatusIs(FileStatus.MD5CHDFromDAT) && fileIn.FileStatusIs(FileStatus.MD5Verified))
                {
                    if (fileIn.MD5 != null && fileOut.MD5 != null && !ArrByte.bCompare(fileIn.MD5, fileOut.MD5))
                    {
                        error = "Source and destination SHA1 does not match. Logic Error.";
                        return ReturnCode.LogicError;
                    }
                }

                #endregion

                #region Find and Check/Open Input Files

                if (fileIn.FileType == FileType.ZipFile) // Input is a ZipFile
                {
                    RvDir zZipFileIn = fileIn.Parent;
                    if (zZipFileIn.FileType != FileType.Zip)
                    {
                        error = "Zip File Open but Source File is not a zip, Logic Error.";
                        return ReturnCode.LogicError;
                    }

                    string fileNameIn = zZipFileIn.FullName;

                    sourceTrrntzip = (zZipFileIn.ZipStatus & ZipStatus.TrrntZip) == ZipStatus.TrrntZip;

                    //if (zZipFileIn.ZipFileType == RvZip.ZipType.Zip)
                    //{
                    zipFileIn = new ZipFile();

                    ZipReturn zr1;
                    if (fileIn.ZipFileHeaderPosition != null)
                        zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.TimeStamp, false);
                    else
                        zr1 = zipFileIn.ZipFileOpen(fileNameIn, zZipFileIn.TimeStamp, true);
                    switch (zr1)
                    {
                        case ZipReturn.ZipGood:
                            break;
                        case ZipReturn.ZipErrorFileNotFound:
                            error = "File not found, Rescan required before fixing " + fileIn.Name;
                            return ReturnCode.FileSystemError;
                        case ZipReturn.ZipErrorTimeStamp:
                            error = "File has changed, Rescan required before fixing " + fileIn.Name;
                            return ReturnCode.FileSystemError;
                        default:
                            error = "Error Open Zip" + zr1 + ", with File " + fileIn.DatFullName;
                            return ReturnCode.FileSystemError;
                    }
                    if (fileIn.ZipFileHeaderPosition != null)
                        zipFileIn.ZipFileOpenReadStreamQuick((ulong)fileIn.ZipFileHeaderPosition, rawCopy, out readStream, out streamSize, out compressionMethod);
                    else
                        zipFileIn.ZipFileOpenReadStream(fileIn.ZipFileIndex, rawCopy, out readStream, out streamSize, out compressionMethod);
                }
                else // Input is a regular file
                {
                    string fileNameIn = fileIn.FullName;
                    if (!IO.File.Exists(fileNameIn))
                    {
                        error = "Rescan needed, File Changed :" + fileNameIn;
                        return ReturnCode.RescanNeeded;
                    }
                    IO.FileInfo fileInInfo = new IO.FileInfo(fileNameIn);
                    if (fileInInfo.LastWriteTime != fileIn.TimeStamp)
                    {
                        error = "Rescan needed, File Changed :" + fileNameIn;
                        return ReturnCode.RescanNeeded;
                    }
                    int errorCode = IO.FileStream.OpenFileRead(fileNameIn, out readStream);
                    if (errorCode != 0)
                    {
                        error = new Win32Exception(errorCode).Message + ". " + fileNameIn;
                        return ReturnCode.FileSystemError;
                    }
                    if (fileIn.Size == null)
                    {
                        error = "Null File Size found in Fixing File :" + fileNameIn;
                        return ReturnCode.LogicError;
                    }
                    streamSize = (ulong)fileIn.Size;
                    if ((ulong)readStream.Length != streamSize)
                    {
                        error = "Rescan needed, File Length Changed :" + fileNameIn;
                        return ReturnCode.RescanNeeded;
                    }
                }
                #endregion
            }
            else
            {
                sourceTrrntzip = true;
            }

            if (!rawCopy && (Settings.FixLevel == eFixLevel.TrrntZipLevel1 || Settings.FixLevel == eFixLevel.TrrntZipLevel2 || Settings.FixLevel == eFixLevel.TrrntZipLevel3))
                compressionMethod = 8;

            #region Find and Check/Open Output Files

            System.IO.Stream writeStream;
            if (fileOut.FileType == FileType.ZipFile)
            {
                // if ZipFileOut == null then we have not open the output zip yet so open it from writing.
                if (zipFileOut == null)
                {
                    if (IO.Path.GetFileName(zipFilenameOut) == "__ROMVault.tmp")
                    {
                        if (IO.File.Exists(zipFilenameOut))
                            IO.File.Delete(zipFilenameOut);
                    }
                    else if (IO.File.Exists(zipFilenameOut))
                    {
                        error = "Rescan needed, File Changed :" + zipFilenameOut;
                        return ReturnCode.RescanNeeded;
                    }

                    zipFileOut = new ZipFile();
                    ZipReturn zrf = zipFileOut.ZipFileCreate(zipFilenameOut);
                    if (zrf != ZipReturn.ZipGood)
                    {
                        error = "Error Opening Write Stream " + zrf;
                        return ReturnCode.FileSystemError;
                    }
                }
                else
                {
                    if (zipFileOut.ZipOpen != ZipOpenType.OpenWrite)
                    {
                        error = "Output Zip File is not set to OpenWrite, Logic Error.";
                        return ReturnCode.LogicError;
                    }

                    if (zipFileOut.ZipFilename != (new IO.FileInfo(zipFilenameOut).FullName))
                    {
                        error = "Output Zip file has changed name from " + zipFileOut.ZipFilename + " to " + zipFilenameOut + ". Logic Error";
                        return ReturnCode.LogicError;
                    }
                }

                if (fileIn.Size == null)
                {
                    error = "Null File Size found in Fixing File :" + fileIn.FullName;
                    return ReturnCode.LogicError;
                }
                ZipReturn zr = zipFileOut.ZipFileOpenWriteStream(rawCopy, sourceTrrntzip, fileOut.Name, (ulong)fileIn.Size, compressionMethod, out writeStream);
                if (zr != ZipReturn.ZipGood)
                {
                    error = "Error Opening Write Stream " + zr;
                    return ReturnCode.FileSystemError;
                }
            }
            else
            {
                if (IO.File.Exists(zipFilenameOut) && fileOut.GotStatus != GotStatus.Corrupt)
                {
                    error = "Rescan needed, File Changed :" + zipFilenameOut;
                    return ReturnCode.RescanNeeded;
                }
                int errorCode = IO.FileStream.OpenFileWrite(zipFilenameOut, out writeStream);
                if (errorCode != 0)
                {
                    error = new Win32Exception(errorCode).Message + ". " + zipFilenameOut;
                    return ReturnCode.FileSystemError;
                }
            }
            #endregion

            byte[] bCRC;
            byte[] bMD5 = null;
            byte[] bSHA1 = null;
            if (!isZeroLengthFile)
            {
                #region Do Data Tranfer

                CRC32Hash crc32 = null;
                MD5 md5 = null;
                SHA1 sha1 = null;

                if (!rawCopy)
                {
                    crc32 = new CRC32Hash();
                    md5 = MD5.Create();
                    sha1 = SHA1.Create();
                }

                ulong sizetogo = streamSize;

                while (sizetogo > 0)
                {
                    int sizenow = sizetogo > BufferSize ? BufferSize : (int)sizetogo;

                    try
                    {
                        readStream.Read(_buffer, 0, sizenow);
                    }
                    catch (ZlibException)
                    {
                        if (fileIn.FileType == FileType.ZipFile && zipFileIn != null)
                        {
                            ZipReturn zr = zipFileIn.ZipFileCloseReadStream();
                            if (zr != ZipReturn.ZipGood)
                            {
                                error = "Error Closing " + zr + " Stream :" + zipFileIn.Filename(fileIn.ReportIndex);
                                return ReturnCode.FileSystemError;
                            }
                            zipFileIn.ZipFileClose();

                        }
                        else
                        {
                            readStream.Close();
                        }

                        if (fileOut.FileType == FileType.ZipFile)
                        {
                            ZipReturn zr = zipFileOut.ZipFileCloseWriteStream(new byte[] { 0, 0, 0, 0 });
                            if (zr != ZipReturn.ZipGood)
                            {
                                error = "Error Closing Stream " + zr;
                                return ReturnCode.FileSystemError;
                            }
                            zipFileOut.ZipFileRollBack();
                        }
                        else
                        {
                            writeStream.Flush();
                            writeStream.Close();
                            IO.File.Delete(zipFilenameOut);
                        }

                        error = "Error in Data Stream";
                        return ReturnCode.SourceCRCCheckSumError;
                    }
                    catch (Exception e)
                    {
                        error = "Error reading Source File " + e.Message;
                        return ReturnCode.FileSystemError;
                    }

                    if (!rawCopy)
                    {
                        crc32.TransformBlock(_buffer, 0, sizenow, null, 0);
                        md5.TransformBlock(_buffer, 0, sizenow, null, 0);
                        sha1.TransformBlock(_buffer, 0, sizenow, null, 0);
                    }
                    try
                    {
                        writeStream.Write(_buffer, 0, sizenow);
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine(e.Message);
                        error = "Error writing out file. " + Environment.NewLine + e.Message;
                        return ReturnCode.FileSystemError;
                    }
                    sizetogo = sizetogo - (ulong)sizenow;
                }
                writeStream.Flush();

                #endregion

                #region Collect Checksums

                // if we did a full copy then we just calculated all the checksums while doing the copy
                if (!rawCopy)
                {

                    crc32.TransformFinalBlock(_buffer, 0, 0);
                    md5.TransformFinalBlock(_buffer, 0, 0);
                    sha1.TransformFinalBlock(_buffer, 0, 0);

                    bCRC = crc32.Hash;
                    bMD5 = md5.Hash;
                    bSHA1 = sha1.Hash;

                }
                // if we raw copied and the source file has been FileChecked then we can trust the checksums in the source file
                else
                {
                    bCRC = ArrByte.Copy(fileIn.CRC);
                    if (fileIn.FileStatusIs(FileStatus.MD5Verified)) bMD5 = ArrByte.Copy(fileIn.MD5);
                    if (fileIn.FileStatusIs(FileStatus.SHA1Verified)) bSHA1 = ArrByte.Copy(fileIn.SHA1);
                }

                #endregion

                #region close the ReadStream

                if (fileIn.FileType == FileType.ZipFile && zipFileIn != null)
                {
                    ZipReturn zr = zipFileIn.ZipFileCloseReadStream();
                    if (zr != ZipReturn.ZipGood)
                    {
                        error = "Error Closing " + zr + " Stream :" + zipFileIn.Filename(fileIn.ReportIndex);
                        return ReturnCode.FileSystemError;
                    }
                    zipFileIn.ZipFileClose();
                }
                else
                {
                    readStream.Close();

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

                #endregion
            }
            else
            {
                // Zero Length File (Directory in a Zip)
                if (fileOut.FileType == FileType.ZipFile)
                {
                    zipFileOut.ZipFileAddDirectory();
                }
                bCRC = VarFix.CleanMD5SHA1("00000000", 8);
                bMD5 = VarFix.CleanMD5SHA1("d41d8cd98f00b204e9800998ecf8427e", 32);
                bSHA1 = VarFix.CleanMD5SHA1("da39a3ee5e6b4b0d3255bfef95601890afd80709", 40);
            }

            #region close the WriteStream
            if (fileOut.FileType == FileType.ZipFile)
            {
                ZipReturn zr = zipFileOut.ZipFileCloseWriteStream(bCRC);
                if (zr != ZipReturn.ZipGood)
                {
                    error = "Error Closing Stream " + zr;
                    return ReturnCode.FileSystemError;
                }
                fileOut.ZipFileIndex = zipFileOut.LocalFilesCount() - 1;
                fileOut.ZipFileHeaderPosition = zipFileOut.LocalHeader(fileOut.ZipFileIndex);
            }
            else
            {
                writeStream.Flush();
                writeStream.Close();
                IO.FileInfo fi = new IO.FileInfo(zipFilenameOut);
                fileOut.TimeStamp = fi.LastWriteTime;
            }
            #endregion

            if (!isZeroLengthFile)
            {

                if (!rawCopy)
                {
                    if (!ArrByte.bCompare(bCRC, fileIn.CRC))
                    {
                        fileIn.GotStatus = GotStatus.Corrupt;
                        error = "Source CRC does not match Source Data stream, corrupt Zip";

                        if (fileOut.FileType == FileType.ZipFile)
                            zipFileOut.ZipFileRollBack();
                        else
                            IO.File.Delete(zipFilenameOut);

                        return ReturnCode.SourceCRCCheckSumError;
                    }

                    fileIn.FileStatusSet(FileStatus.CRCVerified | FileStatus.SizeVerified);

                    bool sourceFailed = false;

                    // check to see if we have a MD5 from the DAT file
                    if (fileIn.FileStatusIs(FileStatus.MD5FromDAT))
                    {
                        if (fileIn.MD5 == null)
                        {
                            error = "Should have an filein MD5 from Dat but not found. Logic Error.";
                            return ReturnCode.LogicError;
                        }

                        if (!ArrByte.bCompare(fileIn.MD5, bMD5))
                            sourceFailed = true;
                        else
                            fileIn.FileStatusSet(FileStatus.MD5Verified);
                    }
                    // check to see if we have an MD5 (not from the DAT) so must be from previously scanning this file.
                    else if (fileIn.MD5 != null)
                    {
                        if (!ArrByte.bCompare(fileIn.MD5, bMD5))
                        {
                            // if we had an MD5 from a preview scan and it now does not match, something has gone really bad.
                            error = "The MD5 found does not match a previously scanned MD5, this should not happen, unless something got corrupt.";
                            return ReturnCode.LogicError;
                        }
                    }
                    else // (FileIn.MD5 == null)
                    {
                        fileIn.MD5 = bMD5;
                        fileIn.FileStatusSet(FileStatus.MD5Verified);
                    }

                    // check to see if we have a SHA1 from the DAT file
                    if (fileIn.FileStatusIs(FileStatus.SHA1FromDAT))
                    {
                        if (fileIn.SHA1 == null)
                        {
                            error = "Should have an filein SHA1 from Dat but not found. Logic Error.";
                            return ReturnCode.LogicError;
                        }

                        if (!ArrByte.bCompare(fileIn.SHA1, bSHA1))
                            sourceFailed = true;
                        else
                            fileIn.FileStatusSet(FileStatus.SHA1Verified);
                    }
                    // check to see if we have an SHA1 (not from the DAT) so must be from previously scanning this file.
                    else if (fileIn.SHA1 != null)
                    {
                        if (!ArrByte.bCompare(fileIn.SHA1, bSHA1))
                        {
                            // if we had an SHA1 from a preview scan and it now does not match, something has gone really bad.
                            error = "The SHA1 found does not match a previously scanned SHA1, this should not happen, unless something got corrupt.";
                            return ReturnCode.LogicError;
                        }
                    }
                    else // (FileIn.SHA1 == null)
                    {
                        fileIn.SHA1 = bSHA1;
                        fileIn.FileStatusSet(FileStatus.SHA1Verified);
                    }

                    if (sourceFailed)
                    {
                        if (fileIn.FileType == FileType.ZipFile)
                        {
                            RvFile tZFile = new RvFile(FileType.ZipFile);
                            foundFile = tZFile;
                            tZFile.ZipFileIndex = fileIn.ZipFileIndex;
                            tZFile.ZipFileHeaderPosition = fileIn.ZipFileHeaderPosition;
                        }
                        else
                        {
                            foundFile = new RvFile(fileIn.FileType);
                        }

                        foundFile.Name = fileIn.Name;
                        foundFile.Size = fileIn.Size;
                        foundFile.CRC = bCRC;
                        foundFile.MD5 = bMD5;
                        foundFile.SHA1 = bSHA1;
                        foundFile.TimeStamp = fileIn.TimeStamp;
                        foundFile.SetStatus(DatStatus.NotInDat, GotStatus.Got);

                        foundFile.FileStatusSet(FileStatus.SizeVerified | FileStatus.CRCVerified | FileStatus.MD5Verified | FileStatus.SHA1Verified);

                        if (fileOut.FileType == FileType.ZipFile)
                            zipFileOut.ZipFileRollBack();
                        else
                            IO.File.Delete(zipFilenameOut);

                        return ReturnCode.SourceCheckSumError;
                    }
                }
            }

            if (fileOut.FileType == FileType.ZipFile)
            {
                fileOut.FileStatusSet(FileStatus.SizeFromHeader | FileStatus.CRCFromHeader);
            }

            if (fileOut.FileStatusIs(FileStatus.CRCFromDAT) && fileOut.CRC != null && !ArrByte.bCompare(fileOut.CRC, bCRC))
            {
                //Rollback the file
                if (fileOut.FileType == FileType.ZipFile)
                    zipFileOut.ZipFileRollBack();
                else
                    IO.File.Delete(zipFilenameOut);

                return ReturnCode.DestinationCheckSumError;
            }

            fileOut.CRC = bCRC;
            if (!rawCopy || fileIn.FileStatusIs(FileStatus.CRCVerified))
                fileOut.FileStatusSet(FileStatus.CRCVerified);

            if (bSHA1 != null)
            {
                if (fileOut.FileStatusIs(FileStatus.SHA1FromDAT) && fileOut.SHA1 != null && !ArrByte.bCompare(fileOut.SHA1, bSHA1))
                {
                    //Rollback the file
                    if (fileOut.FileType == FileType.ZipFile)
                        zipFileOut.ZipFileRollBack();
                    else
                        IO.File.Delete(zipFilenameOut);

                    return ReturnCode.DestinationCheckSumError;
                }

                fileOut.SHA1 = bSHA1;
                fileOut.FileStatusSet(FileStatus.SHA1Verified);
            }

            if (bMD5 != null)
            {
                if (fileOut.FileStatusIs(FileStatus.MD5FromDAT) && fileOut.MD5 != null && !ArrByte.bCompare(fileOut.MD5, bMD5))
                {
                    //Rollback the file
                    if (fileOut.FileType == FileType.ZipFile)
                        zipFileOut.ZipFileRollBack();
                    else
                        IO.File.Delete(zipFilenameOut);

                    return ReturnCode.DestinationCheckSumError;
                }
                fileOut.MD5 = bMD5;
                fileOut.FileStatusSet(FileStatus.MD5Verified);
            }

            if (fileIn.Size != null)
            {
                fileOut.Size = fileIn.Size;
                fileOut.FileStatusSet(FileStatus.SizeVerified);
            }

            if (fileIn.GotStatus == GotStatus.Corrupt)
                fileOut.GotStatus = GotStatus.Corrupt;
            else
                fileOut.GotStatus = GotStatus.Got; // Changes RepStatus to Correct

            fileOut.FileStatusSet(FileStatus.SizeVerified);

            if (fileOut.SHA1CHD == null && fileIn.SHA1CHD != null) fileOut.SHA1CHD = fileIn.SHA1CHD;
            if (fileOut.MD5CHD == null && fileIn.MD5CHD != null) fileOut.MD5CHD = fileIn.MD5CHD;

            fileOut.CHDVersion = fileIn.CHDVersion;

            fileOut.FileStatusSet(FileStatus.SHA1CHDFromHeader | FileStatus.MD5CHDFromHeader | FileStatus.SHA1CHDVerified | FileStatus.MD5CHDVerified, fileIn);

            return ReturnCode.Good;
        }
Exemple #6
0
        private static ReturnCode FixFileCanBeFixed(RvFile fixFile)
        {
            string fixFileFullName = fixFile.FullName;
            CheckCreateParent(fixFile.Parent);

            // check to see if there is already a file with the name of the fixFile, and move it out the way.
            ReturnCode rc = FixFilePreCheckFixFile(fixFile);
            if (rc != ReturnCode.Good)
                return rc;


            // now we can fix the file.
            ZipFile tempZipOut = null;
            RvFile foundFile;
            ReturnCode returnCode;

            if (DBHelper.IsZeroLengthFile(fixFile))
            {
                RvFile fileIn = new RvFile(FileType.File);
                returnCode = FixFileCopy.CopyFile(fileIn, ref tempZipOut, fixFile.FullName, fixFile, false, out _error, out foundFile);

                switch (returnCode)
                {
                    case ReturnCode.Good: // correct reply to continue;
                        break;
                    default:
                        _error = fixFile.FullName + " " + fixFile.RepStatus + " " + returnCode + " : " + _error;
                        ReCheckFile(fixFile);
                        return ReturnCode.StartOver;
                }
                _fixed++;
                return ReturnCode.Good;
            }

#if NEWFINDFIX
                List<RvFile> lstFixRomTable = new List<RvFile>();
                List<RvFile> family = fixFile.MyFamily.Family;
                for (int iFind = 0; iFind < family.Count; iFind++)
                {
                    if (family[iFind].GotStatus == GotStatus.Got && FindFixes.CheckIfMissingFileCanBeFixedByGotFile(fixFile, family[iFind]))
                        lstFixRomTable.Add(family[iFind]);
                }
            RvFile fixingFile = lstFixRomTable[0];
#else

            // search for the database for the file to be used to repair this file:
            List<RvFile> lstFixRomTableCRC;
            DBHelper.RomSearchFindFixes(fixFile, _lstRomTableSortedCRCSize, out lstFixRomTableCRC);

            List<RvFile> lstFixRomTableSHA1CHD;
            DBHelper.RomSearchFindFixesSHA1CHD(fixFile, _lstRomTableSortedSHA1CHD, out lstFixRomTableSHA1CHD);

            if (lstFixRomTableCRC.Count == 0 && lstFixRomTableSHA1CHD.Count == 0)
            {
                // thought we could fix the file, turns out we cannot
                fixFile.GotStatus = GotStatus.NotGot;
                return ReturnCode.Good;
            }

            RvFile fixingFile =
                lstFixRomTableCRC.Count > 0 ?
                lstFixRomTableCRC[0] :
                lstFixRomTableSHA1CHD[0];
#endif
            string fts = fixingFile.FullName;
            ReportProgress(new bgwShowFix(Path.GetDirectoryName(fixFileFullName), "", Path.GetFileName(fixFileFullName), fixFile.Size, "<--", Path.GetDirectoryName(fts), Path.GetFileName(fts), fixingFile.Name));



            returnCode = FixFileCopy.CopyFile(fixingFile, ref tempZipOut, fixFile.FullName, fixFile, false, out _error, out foundFile);

            switch (returnCode)
            {
                case ReturnCode.Good: // correct reply to continue;
                    break;

                case ReturnCode.SourceCRCCheckSumError:
                    {
                        ReportProgress(new bgwShowFixError("CRC Error"));
                        // the file we used for fix turns out to be corrupt

                        // mark the source file as Corrupt
                        fixingFile.GotStatus = GotStatus.Corrupt;

                        // recheck for the fix
                        ReCheckFile(fixFile);

                        CheckReprocess(fixingFile);

                        // and go back one and try again.
                        return ReturnCode.StartOver;
                    }


                case ReturnCode.SourceCheckSumError:
                    {
                        // the file we used for fix turns out not not match its own DAT's correct MD5/SHA1
                        // (Problem with logic here is that it could still match the file being fixed, but this case is not correctly handled)
                        ReportProgress(new bgwShowFixError("Failed"));


                        // remove the file we thought we correctly had (The file that we where trying to use for the fix)
                        if (fixingFile.FileRemove() == EFile.Delete)
                        {
                            _error = "Should not mark for delete as it is in a DAT";
                            return ReturnCode.LogicError;
                        }

                        // possibly use a check here to see if the index of the found file is futher down the zip and so we can just contine
                        // instead of restarting.

                        // add in the actual file we found
                        fixingFile.Parent.ChildAdd(foundFile);
                        AddFoundFile(foundFile);

                        // recheck for the fix
                        ReCheckFile(fixFile);

                        CheckReprocess(fixingFile);

                        // and go back one and try again.
                        return ReturnCode.StartOver;
                    }
                case ReturnCode.DestinationCheckSumError:
                    {
                        ReportProgress(new bgwShowFixError("Failed"));

                        // recheck for the fix
                        ReCheckFile(fixFile);
                        return ReturnCode.StartOver;
                    }
                default:
                    return returnCode;
            }


            CheckReprocessClearList();
            // Check the files that we found that where used to fix this file, and if they not listed as correct files, they can be set to be deleted.
            
#if NEWFINDFIX
            foreach (RvFile file in lstFixRomTable)
            {
                if (file.RepStatus != RepStatus.NeededForFix && file.RepStatus != RepStatus.Rename) continue;
                file.RepStatus = RepStatus.Delete;
                CheckReprocess(file, true);
            }
#else

            foreach (RvFile file in lstFixRomTableCRC)
            {
                if (file.RepStatus != RepStatus.NeededForFix && file.RepStatus != RepStatus.Rename) continue;
                file.RepStatus = RepStatus.Delete;
                CheckReprocess(file, true);
            }
            foreach (RvFile file in lstFixRomTableSHA1CHD)
            {
                if (file.RepStatus != RepStatus.NeededForFix && file.RepStatus != RepStatus.Rename) continue;
                file.RepStatus = RepStatus.Delete;
                CheckReprocess(file, true);
            }
#endif
            CheckReprocessFinalCheck();

            _fixed++;

            return ReturnCode.Good;
        }
 private static bool IsDeepScanned(RvFile tFile)
 {
     return (
                tFile.FileStatusIs(FileStatus.SizeVerified) &&
                tFile.FileStatusIs(FileStatus.CRCVerified) &&
                tFile.FileStatusIs(FileStatus.SHA1Verified) &&
                tFile.FileStatusIs(FileStatus.MD5Verified)
            );
 }
 private static void DeepScanFile(string directory, RvFile tFile)
 {
     string filename = Path.Combine(directory, tFile.Name);
     int errorCode = UnCompFiles.CheckSumRead(filename, true, out tFile.CRC, out tFile.MD5, out tFile.SHA1);
     if (errorCode == 32)
     {
         tFile.GotStatus = GotStatus.FileLocked;
         return;
     }
     if (errorCode != 0)
     {
         ReportError.Show("File: " + filename + " Error: " + new Win32Exception(errorCode).Message + ". Scan Aborted.");
         _fileErrorAbort = true;
         return;
     }
     tFile.FileStatusSet(FileStatus.SizeVerified | FileStatus.CRCVerified | FileStatus.SHA1Verified | FileStatus.MD5Verified);
 }
 private static void ReportFile(TextWriter sw, RvFile f)
 {
     sw.WriteLine(f.ReportIndex.ToString("D8") + " " + ArrByte.ToString(f.CRC) + " " + f.GotStatus.ToString().PadRight(10) + " " + f.RepStatus.ToString().PadRight(15) + " " + f.TreeFullName);
 }
Exemple #10
0
        private void AddRom(RvFile tRomTable, string pathAdd)
        {

            if (tRomTable.DatStatus != DatStatus.InDatMerged || tRomTable.RepStatus != RepStatus.NotCollected || chkBoxShowMerged.Checked)
            {
                RomGrid.Rows.Add();
                int row = RomGrid.Rows.Count - 1;
                RomGrid.Rows[row].Tag = tRomTable;

                for (int i = 0; i < RomGrid.Rows[row].Cells.Count; i++)
                {
                    DataGridViewCellStyle cs = RomGrid.Rows[row].Cells[i].Style;
                    cs.BackColor = _displayColor[(int)tRomTable.RepStatus];
                    cs.ForeColor = _fontColor[(int)tRomTable.RepStatus];
                }
                string fname = pathAdd + tRomTable.Name;
                if (!string.IsNullOrEmpty(tRomTable.FileName))
                    fname += " (Found: " + tRomTable.FileName + ")";
                if (tRomTable.CHDVersion != null)
                    fname += " (V" + tRomTable.CHDVersion + ")";

                RomGrid.Rows[row].Cells["CRom"].Value = fname;

                RomGrid.Rows[row].Cells["CMerge"].Value = tRomTable.Merge;
                RomGrid.Rows[row].Cells["CStatus"].Value = tRomTable.Status;

                string strSize = tRomTable.Size.ToString();
                string flags = "";
                if (tRomTable.FileStatusIs(FileStatus.SizeFromDAT)) flags += "D";
                if (tRomTable.FileStatusIs(FileStatus.SizeFromHeader)) flags += "H";
                if (tRomTable.FileStatusIs(FileStatus.SizeVerified)) flags += "V";
                if (!String.IsNullOrEmpty(flags)) strSize += " (" + flags + ")";
                RomGrid.Rows[row].Cells["CSize"].Value = strSize;

                string strCRC = ArrByte.ToString(tRomTable.CRC);
                flags = "";
                if (tRomTable.FileStatusIs(FileStatus.CRCFromDAT)) flags += "D";
                if (tRomTable.FileStatusIs(FileStatus.CRCFromHeader)) flags += "H";
                if (tRomTable.FileStatusIs(FileStatus.CRCVerified)) flags += "V";
                if (!String.IsNullOrEmpty(flags)) strCRC += " (" + flags + ")";
                RomGrid.Rows[row].Cells["CCRC32"].Value = strCRC;

                if (tRomTable.SHA1CHD == null)
                {
                    string strSHA1 = ArrByte.ToString(tRomTable.SHA1);
                    flags = "";
                    if (tRomTable.FileStatusIs(FileStatus.SHA1FromDAT)) flags += "D";
                    if (tRomTable.FileStatusIs(FileStatus.SHA1FromHeader)) flags += "H";
                    if (tRomTable.FileStatusIs(FileStatus.SHA1Verified)) flags += "V";
                    if (!String.IsNullOrEmpty(flags)) strSHA1 += " (" + flags + ")";
                    RomGrid.Rows[row].Cells["CSHA1"].Value = strSHA1;
                }
                else
                {
                    string strSHA1CHD = "CHD: " + ArrByte.ToString(tRomTable.SHA1CHD);
                    flags = "";
                    if (tRomTable.FileStatusIs(FileStatus.SHA1CHDFromDAT)) flags += "D";
                    if (tRomTable.FileStatusIs(FileStatus.SHA1CHDFromHeader)) flags += "H";
                    if (tRomTable.FileStatusIs(FileStatus.SHA1CHDVerified)) flags += "V";
                    if (!String.IsNullOrEmpty(flags)) strSHA1CHD += " (" + flags + ")";
                    RomGrid.Rows[row].Cells["CSHA1"].Value = strSHA1CHD;
                }

                if (tRomTable.MD5CHD == null)
                {
                    string strMD5 = ArrByte.ToString(tRomTable.MD5);
                    flags = "";
                    if (tRomTable.FileStatusIs(FileStatus.MD5FromDAT)) flags += "D";
                    if (tRomTable.FileStatusIs(FileStatus.MD5FromHeader)) flags += "H";
                    if (tRomTable.FileStatusIs(FileStatus.MD5Verified)) flags += "V";
                    if (!String.IsNullOrEmpty(flags)) strMD5 += " (" + flags + ")";
                    RomGrid.Rows[row].Cells["CMD5"].Value = strMD5;
                }
                else
                {
                    string strMD5CHD = "CHD: " + ArrByte.ToString(tRomTable.MD5CHD);
                    flags = "";
                    if (tRomTable.FileStatusIs(FileStatus.MD5CHDFromDAT)) flags += "D";
                    if (tRomTable.FileStatusIs(FileStatus.MD5CHDFromHeader)) flags += "H";
                    if (tRomTable.FileStatusIs(FileStatus.MD5CHDVerified)) flags += "V";
                    if (!String.IsNullOrEmpty(flags)) strMD5CHD += " (" + flags + ")";
                    RomGrid.Rows[row].Cells["CMD5"].Value = strMD5CHD;
                }

                if (tRomTable.FileType == FileType.ZipFile)
                {
                    RomGrid.Rows[row].Cells["ZipIndex"].Value = tRomTable.ZipFileIndex == -1 ? "" : tRomTable.ZipFileIndex.ToString(CultureInfo.InvariantCulture);
                    RomGrid.Rows[row].Cells["ZipHeader"].Value = tRomTable.ZipFileHeaderPosition == null ? "" : tRomTable.ZipFileHeaderPosition.ToString();
                }
            }
        }
Exemple #11
0
        /*
         * In the mame Dat:
         * status="nodump" has a size but no CRC
         * status="baddump" has a size and crc
         */


        private static void RomCheckCollect(RvFile tRom, bool merge)
        {
            if (merge)
            {
                if (string.IsNullOrEmpty(tRom.Merge))
                    tRom.Merge = "(Auto Merged)";

                tRom.DatStatus = DatStatus.InDatMerged;
                return;
            }

            if (!string.IsNullOrEmpty(tRom.Merge))
                tRom.Merge = "(No-Merge) " + tRom.Merge;

            if (tRom.Status == "nodump")
            {
                tRom.CRC = null;
                tRom.DatStatus = DatStatus.InDatBad;
                return;
            }

            if (ArrByte.bCompare(tRom.CRC, new byte[] { 0, 0, 0, 0 }) && tRom.Size == 0)
            {
                tRom.DatStatus = DatStatus.InDatCollect;
                return;
            }

            /*
            if (ArrByte.bCompare(tRom.CRC, new byte[] { 0, 0, 0, 0 }) || (tRom.CRC.Length != 8))
            {
                tRom.CRC = null;
                tRom.DatStatus = DatStatus.InDatBad;
                return;
            }
            */

            tRom.DatStatus = DatStatus.InDatCollect;
        }
Exemple #12
0
        private static ReturnCode FixZip(RvDir fixZip)
        {
            //Check for error status
            if (fixZip.DirStatus.HasUnknown())
                return ReturnCode.FindFixes; // Error

            bool needsTrrntzipped = fixZip.ZipStatus != ZipStatus.TrrntZip && fixZip.GotStatus == GotStatus.Got && fixZip.DatStatus == DatStatus.InDatCollect && (Settings.FixLevel == eFixLevel.TrrntZipLevel1 || Settings.FixLevel == eFixLevel.TrrntZipLevel2 || Settings.FixLevel == eFixLevel.TrrntZipLevel3);

            // file corrupt and not in tosort
            //      if file cannot be fully fixed copy to corrupt
            //      process zipfile

            if (fixZip.GotStatus == GotStatus.Corrupt && fixZip.DatStatus != DatStatus.InToSort)
            {
                ReturnCode movReturnCode = MoveZiptoCorrupt(fixZip);
                if (movReturnCode != ReturnCode.Good)
                    return movReturnCode;
            }

            // has fixable
            //      process zipfile

            else if (fixZip.DirStatus.HasFixable())
            {
                // do nothing here but continue on to process zip.
            }

            // need trrntzipped
            //      process zipfile

            else if (needsTrrntzipped)
            {
                // do nothing here but continue on to process zip.
            }


            // got empty zip that should be deleted
            //      process zipfile
            else if (fixZip.GotStatus == GotStatus.Got && fixZip.GotStatus != GotStatus.Corrupt && !fixZip.DirStatus.HasAnyFiles())
            {
                // do nothing here but continue on to process zip.
            }

            // else
            //      skip this zipfile
            else
            {
                // nothing can be done to return
                return ReturnCode.Good;
            }



            string fixZipFullName = fixZip.TreeFullName;

            if (!fixZip.DirStatus.HasFixable() && needsTrrntzipped)
                ReportProgress(new bgwShowFix(Path.GetDirectoryName(fixZipFullName), Path.GetFileName(fixZipFullName), "", 0, "TrrntZipping", "", "", ""));


            CheckCreateParent(fixZip.Parent);
            ReportError.LogOut("");
            ReportError.LogOut(fixZipFullName + " : " + fixZip.RepStatus);
            ReportError.LogOut("------------------------------------------------------------");
            Debug.WriteLine(fixZipFullName + " : " + fixZip.RepStatus);
            ReportError.LogOut("Zip File Status Before Fix:");
            for (int intLoop = 0; intLoop < fixZip.ChildCount; intLoop++)
                ReportError.LogOut((RvFile)fixZip.Child(intLoop));
            ReportError.LogOut("");

            ZipFile tempZipOut = null;

            ZipFile toSortCorruptOut = null;
            ZipFile toSortZipOut = null;

            RvDir toSortGame = null;
            RvDir toSortCorruptGame = null;

            ReturnCode returnCode;
            List<RvFile> fixZipTemp = new List<RvFile>();

            for (int iRom = 0; iRom < fixZip.ChildCount; iRom++)
            {
                RvFile zipFileFixing = new RvFile(FileType.ZipFile);
                fixZip.Child(iRom).CopyTo(zipFileFixing);

                if (iRom == fixZipTemp.Count)
                    fixZipTemp.Add(zipFileFixing);
                else
                    fixZipTemp[iRom] = zipFileFixing;

                ReportError.LogOut(zipFileFixing.RepStatus + " : " + fixZip.Child(iRom).FullName);

                switch (zipFileFixing.RepStatus)
                {
                    #region Nothing to copy
                    // any file we do not have or do not want in the destination zip
                    case RepStatus.Missing:
                    case RepStatus.NotCollected:
                    case RepStatus.Rename:
                    case RepStatus.Delete:
                        if (!
                              (
                            // got the file in the original zip but will be deleting it
                                (zipFileFixing.DatStatus == DatStatus.NotInDat && zipFileFixing.GotStatus == GotStatus.Got) ||
                                (zipFileFixing.DatStatus == DatStatus.NotInDat && zipFileFixing.GotStatus == GotStatus.Corrupt) ||
                                (zipFileFixing.DatStatus == DatStatus.InDatMerged && zipFileFixing.GotStatus == GotStatus.Got) ||
                                (zipFileFixing.DatStatus == DatStatus.InToSort && zipFileFixing.GotStatus == GotStatus.Got) ||
                                (zipFileFixing.DatStatus == DatStatus.InToSort && zipFileFixing.GotStatus == GotStatus.Corrupt) ||

                                // do not have this file and cannot fix it here
                                (zipFileFixing.DatStatus == DatStatus.InDatCollect && zipFileFixing.GotStatus == GotStatus.NotGot) ||
                                (zipFileFixing.DatStatus == DatStatus.InDatBad && zipFileFixing.GotStatus == GotStatus.NotGot) ||
                                (zipFileFixing.DatStatus == DatStatus.InDatMerged && zipFileFixing.GotStatus == GotStatus.NotGot)
                                )
                            )
                            ReportError.SendAndShow(Resources.FixFiles_FixZip_Error_in_Fix_Rom_Status + zipFileFixing.RepStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.DatStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.GotStatus);

                        if (zipFileFixing.RepStatus == RepStatus.Delete)
                        {
                            returnCode = DoubleCheckDelete(zipFileFixing);
                            if (returnCode != ReturnCode.Good)
                                goto ZipOpenFailed;
                        }

                        zipFileFixing.GotStatus = GotStatus.NotGot;
                        break;
                    #endregion
                    #region Copy from Original to Destination
                    // any files we are just moving from the original zip to the destination zip
                    case RepStatus.Correct:
                    case RepStatus.InToSort:
                    case RepStatus.NeededForFix:
                    case RepStatus.Corrupt:
                        {
                            if (!
                                  (
                                    (zipFileFixing.DatStatus == DatStatus.InDatCollect && zipFileFixing.GotStatus == GotStatus.Got) ||
                                    (zipFileFixing.DatStatus == DatStatus.InDatMerged && zipFileFixing.GotStatus == GotStatus.Got) ||
                                    (zipFileFixing.DatStatus == DatStatus.NotInDat && zipFileFixing.GotStatus == GotStatus.Got) ||
                                    (zipFileFixing.DatStatus == DatStatus.InToSort && zipFileFixing.GotStatus == GotStatus.Got) ||
                                    (zipFileFixing.DatStatus == DatStatus.InToSort && zipFileFixing.GotStatus == GotStatus.Corrupt)
                                  )
                                )
                                ReportError.SendAndShow(Resources.FixFiles_FixZip_Error_in_Fix_Rom_Status + zipFileFixing.RepStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.DatStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.GotStatus);

                            RvFile foundFile;

                            bool rawcopy = (zipFileFixing.RepStatus == RepStatus.InToSort) || (zipFileFixing.RepStatus == RepStatus.Corrupt);
                            // Correct      rawcopy=false
                            // NeededForFix rawcopy=false
                            // InToSort     rawcopy=true
                            // Corrupt      rawcopy=true
                            RepStatus originalStatus = zipFileFixing.RepStatus;

                            returnCode = FixFileCopy.CopyFile(
                                (RvFile)fixZip.Child(iRom),
                                ref tempZipOut,
                                Path.Combine(fixZip.Parent.FullName, "__RomVault.tmp"),
                                zipFileFixing, rawcopy,
                                out _error, out foundFile);

                            switch (returnCode)
                            {
                                case ReturnCode.Good: // correct reply to continue;
                                    if (originalStatus == RepStatus.NeededForFix)
                                        zipFileFixing.RepStatus = RepStatus.NeededForFix;
                                    break;
                                case ReturnCode.SourceCRCCheckSumError:
                                    {
                                        RvFile tFile = (RvFile)fixZip.Child(iRom);
                                        tFile.GotStatus = GotStatus.Corrupt;
                                        ReCheckFile(tFile);

                                        //decrease index so this file gets reprocessed
                                        iRom--;

                                        continue;
                                    }
                                case ReturnCode.SourceCheckSumError:
                                    {
                                        // Set the file in the zip that we thought we correctly had as missing
                                        RvFile tFile = (RvFile)fixZip.Child(iRom);
                                        if (tFile.FileRemove() == EFile.Delete)
                                        {
                                            _error = "Should not mark for delete as it is in a DAT";
                                            return ReturnCode.LogicError;
                                        }

                                        // Add in at the current location the incorrect file. (This file will be reprocessed and then at some point deleted.)
                                        fixZip.ChildAdd(foundFile, iRom);
                                        AddFoundFile(foundFile);

                                        ReCheckFile(tFile);

                                        //decrease index so this file gets reprocessed
                                        iRom--;

                                        continue;
                                    }
                                // not needed as source and destination are the same
                                // case ReturnCode.DestinationCheckSumError:  
                                default:
                                    _error = zipFileFixing.FullName + " " + zipFileFixing.RepStatus + " " + returnCode + " : " + _error;
                                    goto ZipOpenFailed;
                            }
                        }
                        break;
                    #endregion

                    #region Case.CanBeFixed
                    case RepStatus.CanBeFixed:
                    case RepStatus.CorruptCanBeFixed:
                        {
                            if (!(zipFileFixing.DatStatus == DatStatus.InDatCollect && (zipFileFixing.GotStatus == GotStatus.NotGot || zipFileFixing.GotStatus == GotStatus.Corrupt)))
                                ReportError.SendAndShow(Resources.FixFiles_FixZip_Error_in_Fix_Rom_Status + zipFileFixing.RepStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.DatStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.GotStatus);

                            ReportError.LogOut("Fixing File:");
                            ReportError.LogOut(zipFileFixing);

                            string strPath = fixZip.Parent.FullName;
                            string tempZipFilename = Path.Combine(strPath, "__RomVault.tmp");


                            if (DBHelper.IsZeroLengthFile(zipFileFixing))
                            {
                                RvFile fileIn = new RvFile(FileType.ZipFile) { Size = 0 };
                                RvFile foundFile;
                                returnCode = FixFileCopy.CopyFile(fileIn, ref tempZipOut, tempZipFilename, zipFileFixing, false, out _error, out foundFile);

                                switch (returnCode)
                                {
                                    case ReturnCode.Good: // correct reply to continue;
                                        break;
                                    default:
                                        _error = zipFileFixing.FullName + " " + zipFileFixing.RepStatus + " " + returnCode + " : " + _error;
                                        goto ZipOpenFailed;
                                }
                                break;
                            }

#if NEWFINDFIX
                            List<RvFile> lstFixRomTable = new List<RvFile>();
                            List<RvFile> family = zipFileFixing.MyFamily.Family;
                            for (int iFind = 0; iFind < family.Count; iFind++)
                            {
                                if (family[iFind].GotStatus == GotStatus.Got && FindFixes.CheckIfMissingFileCanBeFixedByGotFile(zipFileFixing, family[iFind]))
                                    lstFixRomTable.Add(family[iFind]);
                            }
#else
                            List<RvFile> lstFixRomTable;
                            DBHelper.RomSearchFindFixes(zipFileFixing, _lstRomTableSortedCRCSize, out lstFixRomTable);
#endif

                            ReportError.LogOut("Found Files To use for Fixes:");
                            foreach (RvFile t in lstFixRomTable)
                                ReportError.LogOut(t);

                            if (lstFixRomTable.Count > 0)
                            {

                                string ts = lstFixRomTable[0].Parent.FullName;
                                string sourceDir;
                                string sourceFile;
                                if (lstFixRomTable[0].FileType == FileType.ZipFile)
                                {
                                    sourceDir = Path.GetDirectoryName(ts);
                                    sourceFile = Path.GetFileName(ts);
                                }
                                else
                                {
                                    sourceDir = ts;
                                    sourceFile = "";
                                }
                                ReportProgress(new bgwShowFix(Path.GetDirectoryName(fixZipFullName), Path.GetFileName(fixZipFullName), zipFileFixing.Name, zipFileFixing.Size, "<--", sourceDir, sourceFile, lstFixRomTable[0].Name));

                                RvFile foundFile;
                                returnCode = FixFileCopy.CopyFile(lstFixRomTable[0], ref tempZipOut, tempZipFilename, zipFileFixing, false, out _error, out foundFile);
                                switch (returnCode)
                                {
                                    case ReturnCode.Good: // correct reply so continue;
                                        break;

                                    case ReturnCode.SourceCRCCheckSumError:
                                        {
                                            ReportProgress(new bgwShowFixError("CRC Error"));
                                            // the file we used for fix turns out to be corrupt

                                            RvFile tFile = (RvFile)fixZip.Child(iRom);

                                            // mark the source file as Corrupt
                                            lstFixRomTable[0].GotStatus = GotStatus.Corrupt;

                                            // recheck for the fix
                                            ReCheckFile(tFile);

                                            // if the file being used from the fix is actually from this file then we have a big mess, and we are just going to
                                            // start over on this zip.
                                            if (lstFixRomTable[0].Parent == fixZip)
                                            {
                                                returnCode = ReturnCode.StartOver;
                                                goto ZipOpenFailed;
                                            }

                                            // add the fixing source zip into the processList so that it is also reprocessed and we just changed it.
                                            if (!_processList.Contains(lstFixRomTable[0].Parent))
                                                _processList.Add(lstFixRomTable[0].Parent);

                                            // and go back one and try again.
                                            iRom--;
                                            continue;
                                        }


                                    case ReturnCode.SourceCheckSumError:
                                        {
                                            ReportProgress(new bgwShowFixError("Failed"));
                                            // the file we used for fix turns out not not match its own DAT's correct MD5/SHA1
                                            // (Problem with logic here is that it could still match the file being fixed, but this case is not correctly handled)

                                            RvFile tFile = (RvFile)fixZip.Child(iRom);

                                            // remove the file we thought we correctly had (The file that we where trying to use for the fix)
                                            if (lstFixRomTable[0].FileRemove() == EFile.Delete)
                                            {
                                                _error = "Should not mark for delete as it is in a DAT";
                                                return ReturnCode.LogicError;
                                            }

                                            // possibly use a check here to see if the index of the found file is futher down the zip and so we can just contine
                                            // instead of restarting.

                                            // add in the actual file we found
                                            lstFixRomTable[0].Parent.ChildAdd(foundFile);
                                            AddFoundFile(foundFile);

                                            // recheck for the fix
                                            ReCheckFile(tFile);

                                            // if the file being used from the fix is actually from this file then we have a big mess, and we are just going to
                                            // start over on this zip.
                                            if (lstFixRomTable[0].Parent == fixZip)
                                            {
                                                returnCode = ReturnCode.StartOver;
                                                goto ZipOpenFailed;
                                            }

                                            // add the fixing source zip into the processList so that it is also reprocessed and we just changed it.
                                            if (!_processList.Contains(lstFixRomTable[0].Parent))
                                                _processList.Add(lstFixRomTable[0].Parent);

                                            // and go back one and try again.
                                            iRom--;
                                            continue;
                                        }
                                    case ReturnCode.DestinationCheckSumError:
                                        {
                                            ReportProgress(new bgwShowFixError("Failed"));
                                            // the file we used for fix turns out not to have the correct MD5/SHA1 
                                            RvFile tFile = (RvFile)fixZip.Child(iRom);

                                            // recheck for the fix
                                            ReCheckFile(tFile);

                                            // if the file being used from the fix is actually from this file then we have a big mess, and we are just going to
                                            // start over on this zip.
                                            // The need for this is that the file being pulled in from inside this zip will be marked as Rename
                                            // and so would then automatically be deleted, in the case this exception happens, this source file instead
                                            // should be set to move to tosort. 
                                            if (lstFixRomTable[0].Parent == fixZip)
                                            {
                                                returnCode = ReturnCode.StartOver;
                                                goto ZipOpenFailed;
                                            }

                                            // and go back one and try again.
                                            iRom--;
                                            continue;
                                        }
                                    default:
                                        //_error = zipFileFixing.FullName + " " + zipFileFixing.RepStatus + " " + returnCode + Environment.NewLine + _error;
                                        goto ZipOpenFailed;
                                }

                                //Check to see if the files used for fix, can now be set to delete
                                CheckReprocessClearList();

                                foreach (RvFile tFixRom in lstFixRomTable)
                                {
                                    if (tFixRom.RepStatus == RepStatus.NeededForFix)
                                    {
                                        tFixRom.RepStatus = RepStatus.Delete;
                                        ReportError.LogOut("Setting File Status to Delete:");
                                        ReportError.LogOut(tFixRom);
                                        CheckReprocess(tFixRom, true);
                                    }
                                }
                                CheckReprocessFinalCheck();

                                _fixed++;
                            }
                            else
                                // thought we could fix it, turns out we cannot
                                zipFileFixing.GotStatus = GotStatus.NotGot;
                        }
                        break;
                    #endregion
                    #region Case.MoveToSort
                    case RepStatus.MoveToSort:
                        {
                            if (!(zipFileFixing.DatStatus == DatStatus.NotInDat && zipFileFixing.GotStatus == GotStatus.Got))
                                ReportError.SendAndShow(Resources.FixFiles_FixZip_Error_in_Fix_Rom_Status + zipFileFixing.RepStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.DatStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.GotStatus);

                            ReportError.LogOut("Moving File out to ToSort:");
                            ReportError.LogOut(zipFileFixing);
                            // move the rom out to the To Sort Directory

                            if (toSortGame == null)
                            {
                                string toSortFullName = Path.Combine(Settings.ToSort(), fixZip.Name + ".zip");
                                string toSortFileName = fixZip.Name;
                                int fileC = 0;
                                while (File.Exists(toSortFullName))
                                {
                                    fileC++;
                                    toSortFullName = Path.Combine(Settings.ToSort(), fixZip.Name + fileC + ".zip");
                                    toSortFileName = fixZip.Name + fileC;
                                }

                                toSortGame = new RvDir(FileType.Zip)
                                                 {
                                                     Name = toSortFileName,
                                                     DatStatus = DatStatus.InToSort,
                                                     GotStatus = GotStatus.Got
                                                 };
                            }

                            RvFile toSortRom = new RvFile(FileType.ZipFile)
                                                      {
                                                          Name = zipFileFixing.Name,
                                                          Size = zipFileFixing.Size,
                                                          CRC = zipFileFixing.CRC,
                                                          SHA1 = zipFileFixing.SHA1,
                                                          MD5 = zipFileFixing.MD5
                                                      };
                            toSortRom.SetStatus(DatStatus.InToSort, GotStatus.Got);
                            toSortRom.FileStatusSet(
                                FileStatus.SizeFromHeader | FileStatus.SizeVerified |
                                FileStatus.CRCFromHeader | FileStatus.CRCVerified |
                                FileStatus.SHA1FromHeader | FileStatus.SHA1Verified |
                                FileStatus.MD5FromHeader | FileStatus.MD5Verified
                                , zipFileFixing);

                            toSortGame.ChildAdd(toSortRom);

                            string destination = Path.Combine(Settings.ToSort(), toSortGame.Name + ".zip");
                            ReportProgress(new bgwShowFix(Path.GetDirectoryName(fixZipFullName), Path.GetFileName(fixZipFullName), zipFileFixing.Name, zipFileFixing.Size, "-->", "ToSort", Path.GetFileName(destination), toSortRom.Name));

                            RvFile foundFile;
                            returnCode = FixFileCopy.CopyFile((RvFile)fixZip.Child(iRom), ref toSortZipOut, destination, toSortRom, true, out _error, out foundFile);
                            switch (returnCode)
                            {
                                case ReturnCode.Good: // correct reply to continue;
                                    break;
                                //raw copying so Checksums are not checked
                                //case ReturnCode.SourceCRCCheckSumError: 
                                //case ReturnCode.SourceCheckSumError:
                                //case ReturnCode.DestinationCheckSumError: 
                                default:
                                    _error = zipFileFixing.FullName + " " + zipFileFixing.RepStatus + " " + returnCode + " : " + _error;
                                    goto ZipOpenFailed;
                            }
                            zipFileFixing.GotStatus = GotStatus.NotGot; // Changes RepStatus to Deleted
                        }
                        break;
                    #endregion
                    #region Case.MoveToCorrupt
                    case RepStatus.MoveToCorrupt:
                        {
                            if (!((zipFileFixing.DatStatus == DatStatus.InDatCollect || zipFileFixing.DatStatus == DatStatus.NotInDat) && zipFileFixing.GotStatus == GotStatus.Corrupt))
                                ReportError.SendAndShow(Resources.FixFiles_FixZip_Error_in_Fix_Rom_Status + zipFileFixing.RepStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.DatStatus + Resources.FixFiles_FixZip_Colon + zipFileFixing.GotStatus);

                            ReportError.LogOut("Moving File to Corrupt");
                            ReportError.LogOut(zipFileFixing);

                            string toSortFullName;
                            if (toSortCorruptGame == null)
                            {
                                string corruptDir = Path.Combine(Settings.ToSort(), "Corrupt");
                                if (!Directory.Exists(corruptDir))
                                {
                                    Directory.CreateDirectory(corruptDir);
                                }

                                toSortFullName = Path.Combine(corruptDir, fixZip.Name + ".zip");
                                string toSortFileName = fixZip.Name;
                                int fileC = 0;
                                while (File.Exists(toSortFullName))
                                {
                                    fileC++;
                                    toSortFullName = Path.Combine(corruptDir, fixZip.Name + fileC + ".zip");
                                    toSortFileName = fixZip.Name + fileC;
                                }

                                toSortCorruptGame = new RvDir(FileType.Zip)
                                                        {
                                                            Name = toSortFileName,
                                                            DatStatus = DatStatus.InToSort,
                                                            GotStatus = GotStatus.Got
                                                        };
                            }
                            else
                            {
                                string corruptDir = Path.Combine(Settings.ToSort(), "Corrupt");
                                toSortFullName = Path.Combine(corruptDir, toSortCorruptGame.Name + ".zip");
                            }

                            RvFile toSortCorruptRom = new RvFile(FileType.ZipFile)
                                                             {
                                                                 Name = zipFileFixing.Name,
                                                                 Size = zipFileFixing.Size,
                                                                 CRC = zipFileFixing.CRC
                                                             };
                            toSortCorruptRom.SetStatus(DatStatus.InToSort, GotStatus.Corrupt);
                            toSortCorruptGame.ChildAdd(toSortCorruptRom);

                            ReportProgress(new bgwShowFix(Path.GetDirectoryName(fixZipFullName), Path.GetFileName(fixZipFullName), zipFileFixing.Name, zipFileFixing.Size, "-->", "Corrupt", Path.GetFileName(toSortFullName), zipFileFixing.Name));

                            RvFile foundFile;
                            returnCode = FixFileCopy.CopyFile((RvFile)fixZip.Child(iRom), ref toSortCorruptOut, toSortFullName, toSortCorruptRom, true, out _error, out foundFile);
                            switch (returnCode)
                            {
                                case ReturnCode.Good: // correct reply to continue;
                                    break;

                                // doing a raw copy so not needed
                                // case ReturnCode.SourceCRCCheckSumError: 
                                // case ReturnCode.SourceCheckSumError:
                                // case ReturnCode.DestinationCheckSumError: 
                                default:
                                    _error = zipFileFixing.FullName + " " + zipFileFixing.RepStatus + " " + returnCode + " : " + _error;
                                    goto ZipOpenFailed;
                            }
                            zipFileFixing.GotStatus = GotStatus.NotGot;
                        }
                        break;
                    #endregion
                    default:



                        ReportError.UnhandledExceptionHandler("Unknown file status found " + zipFileFixing.RepStatus + " while fixing file " + fixZip.Name + " Dat Status = " + zipFileFixing.DatStatus + " GotStatus " + zipFileFixing.GotStatus);
                        break;
                }
            }


            #region if ToSort Zip Made then close the zip and add this new zip to the Database
            if (toSortGame != null)
            {
                toSortZipOut.ZipFileClose();

                toSortGame.TimeStamp = toSortZipOut.TimeStamp;
                toSortGame.DatStatus = DatStatus.InToSort;
                toSortGame.GotStatus = GotStatus.Got;
                toSortGame.ZipStatus = toSortZipOut.ZipStatus;

                RvDir toSort = (RvDir)DB.DirTree.Child(1);
                toSort.ChildAdd(toSortGame);
            }
            #endregion

            #region if Corrupt Zip Made then close the zip and add this new zip to the Database
            if (toSortCorruptGame != null)
            {
                toSortCorruptOut.ZipFileClose();

                toSortCorruptGame.TimeStamp = toSortCorruptOut.TimeStamp;
                toSortCorruptGame.DatStatus = DatStatus.InToSort;
                toSortCorruptGame.GotStatus = GotStatus.Got;

                RvDir toSort = (RvDir)DB.DirTree.Child(1);
                int indexcorrupt;
                RvDir corruptDir = new RvDir(FileType.Dir) { Name = "Corrupt", DatStatus = DatStatus.InToSort };
                int found = toSort.ChildNameSearch(corruptDir, out indexcorrupt);
                if (found != 0)
                {
                    corruptDir.GotStatus = GotStatus.Got;
                    indexcorrupt = toSort.ChildAdd(corruptDir);
                }
                ((RvDir)toSort.Child(indexcorrupt)).ChildAdd(toSortCorruptGame);
            }
            #endregion



            #region Process original Zip
            string filename = fixZip.FullName;
            if (File.Exists(filename))
            {
                if (!File.SetAttributes(filename, FileAttributes.Normal))
                {
                    int error = Error.GetLastError();
                    ReportProgress(new bgwShowError(filename, "Error Setting File Attributes to Normal. Deleting Original Fix File. Code " + error));
                }
                try
                {
                    File.Delete(filename);
                }
                catch (Exception)
                {
                    int error = Error.GetLastError();
                    _error = "Error While trying to delete file " + filename + ". Code " + error;

                    if (tempZipOut != null && tempZipOut.ZipOpen != ZipOpenType.Closed)
                        tempZipOut.ZipFileClose();

                    return ReturnCode.RescanNeeded;
                }

            }
            #endregion

            bool checkDelete = false;
            #region process the temp Zip rename it to the original Zip
            if (tempZipOut != null && tempZipOut.ZipOpen != ZipOpenType.Closed)
            {
                string tempFilename = tempZipOut.ZipFilename;
                tempZipOut.ZipFileClose();

                if (tempZipOut.LocalFilesCount() > 0)
                {
                    // now rename the temp fix file to the correct filename
                    File.Move(tempFilename, filename);
                    FileInfo nFile = new FileInfo(filename);
                    RvDir tmpZip = new RvDir(FileType.Zip)
                                       {
                                           Name = Path.GetFileNameWithoutExtension(filename),
                                           TimeStamp = nFile.LastWriteTime
                                       };
                    tmpZip.SetStatus(fixZip.DatStatus, GotStatus.Got);

                    fixZip.FileAdd(tmpZip);
                    fixZip.ZipStatus = tempZipOut.ZipStatus;
                }
                else
                {
                    File.Delete(tempFilename);
                    checkDelete = true;
                }
            }
            else
                checkDelete = true;
            #endregion

            #region Now put the New Game Status information into the Database.
            int intLoopFix = 0;
            foreach (RvFile tmpZip in fixZipTemp)
            {
                tmpZip.CopyTo(fixZip.Child(intLoopFix));

                if (fixZip.Child(intLoopFix).RepStatus == RepStatus.Deleted)
                    if (fixZip.Child(intLoopFix).FileRemove() == EFile.Delete)
                    {
                        fixZip.ChildRemove(intLoopFix);
                        continue;
                    }

                intLoopFix++;
            }
            #endregion

            if (checkDelete)
                CheckDeleteObject(fixZip);

            ReportError.LogOut("");
            ReportError.LogOut("Zip File Status After Fix:");
            for (int intLoop = 0; intLoop < fixZip.ChildCount; intLoop++)
                ReportError.LogOut((RvFile)fixZip.Child(intLoop));
            ReportError.LogOut("");

            return ReturnCode.Good;


        ZipOpenFailed:
            if (tempZipOut != null) tempZipOut.ZipFileCloseFailed();
            if (toSortZipOut != null) toSortZipOut.ZipFileCloseFailed();
            if (toSortCorruptOut != null) toSortCorruptOut.ZipFileCloseFailed();
            return returnCode;

        }
        public static bool RomFromSameGame(RvFile a, RvFile b)
        {
            if (a.Parent == null)
                return false;
            if (b.Parent == null)
                return false;

            return a.Parent == b.Parent;
        }
        public static bool IsZeroLengthFile(RvFile tFile)
        {
            if (tFile.MD5 != null)
            {
                if (!ArrByte.bCompare(tFile.MD5, ZeroByteMD5))
                    return false;
            }

            if (tFile.SHA1 != null)
            {
                if (!ArrByte.bCompare(tFile.SHA1, ZeroByteSHA1))
                    return false;
            }

            if (tFile.CRC != null)
                if (!ArrByte.bCompare(tFile.CRC, ZeroByteCRC))
                    return false;

            return tFile.Size == 0;
        }
Exemple #15
0
 public void FileStatusSet(FileStatus flag, RvFile copyFrom)
 {
     _fileStatus |= flag & copyFrom._fileStatus;
 }
 public void FileStatusSet(FileStatus flag, RvFile copyFrom)
 {
     _fileStatus |= (flag & copyFrom._fileStatus);
 }
        private static bool LoadRomFromDat(ref RvDir tGame, FileType thisFileType)
        {
            if (DatFileLoader.Next != "(")
            {
                DatUpdate.SendAndShowDat(Resources.DatCmpReader_LoadRomFromDat_not_found_after_rom, DatFileLoader.Filename);
                return false;
            }
            string line=DatFileLoader.GnRest();
            string linelc = line.ToLower();

            int posName = linelc.IndexOf("name ", StringComparison.Ordinal);
            int posSize = linelc.IndexOf(" size ", posName+5,StringComparison.Ordinal);
            int posDate = linelc.IndexOf(" date ", posSize+6,StringComparison.Ordinal);
            int posCrc = linelc.IndexOf(" crc ", posDate+6,StringComparison.Ordinal);
            int posEnd = linelc.IndexOf(" )", posCrc+5,StringComparison.Ordinal);

            if (posName < 0 || posSize < 0 || posDate < 0 || posCrc < 0 || posEnd < 0)
            {
                DatFileLoader.Gn();
                return false;
            }

            string name = line.Substring(posName + 5, posSize - (posName + 5));
            string size = line.Substring(posSize + 6, posDate - (posSize + 6));
            //string date = line.Substring(posDate + 6, posCrc - (posDate + 6));
            string crc = line.Substring(posCrc + 5, posEnd - (posCrc + 5));

            RvFile tRom = new RvFile(thisFileType)
                              {
                                  Dat = tGame.Dat,
                                  Name = VarFix.CleanFullFileName(name.Trim()),
                                  Size = VarFix.ULong(size.Trim()),
                                  CRC = VarFix.CleanMD5SHA1(crc.Trim(), 8)
                              };

            if (tRom.Size != null) tRom.FileStatusSet(FileStatus.SizeFromDAT);
            if (tRom.CRC != null) tRom.FileStatusSet(FileStatus.CRCFromDAT);

            tGame.ChildAdd(tRom);

            return true;
        }
        private static bool CheckIfGotfileAndMatchingFileAreFullMatches(RvFile gotFile, RvFile matchingFile)
        {
            if (gotFile.FileStatusIs(FileStatus.SHA1Verified) && matchingFile.FileStatusIs(FileStatus.SHA1Verified) && !ArrByte.bCompare(gotFile.SHA1, matchingFile.SHA1))
                return false;
            if (gotFile.FileStatusIs(FileStatus.MD5Verified) && matchingFile.FileStatusIs(FileStatus.MD5Verified) && !ArrByte.bCompare(gotFile.MD5, matchingFile.MD5))
                return false;

            return true;
        }
        // find all of the files that we have that match the needed SHA1 CHD.
        public static void RomSearchFindFixesSHA1CHD(RvFile tRom, List<RvFile> lstFiles, out List<RvFile> lstFilesOut)
        {
            lstFilesOut = new List<RvFile>();
            if (tRom.SHA1CHD == null)
                return;

            int intIndex;
            int intRes = RomSearchSHA1CHD(tRom, lstFiles, out intIndex);

            while (intRes == 0)
            {
                if (lstFiles[intIndex].GotStatus == GotStatus.Got)
                    lstFilesOut.Add(lstFiles[intIndex]);

                intIndex++;
                intRes = intIndex < lstFiles.Count ? RomSortSHA1CHDFunc(lstFiles[intIndex], tRom) : 1;
            }
        }
        private static void LoadRomFromDat(ref RvDir tGame, XmlNode romNode, FileType thisFileType)
        {
            if (romNode.Attributes == null)
                return;


            RvFile tRom = new RvFile(thisFileType)
                              {
                                  Dat = tGame.Dat,
                                  Size = VarFix.ULong(romNode.Attributes.GetNamedItem("size")),
                                  Name = VarFix.CleanFullFileName(romNode.Attributes.GetNamedItem("name")),
                                  CRC = VarFix.CleanMD5SHA1(romNode.Attributes.GetNamedItem("crc"), 8),
                                  SHA1 = VarFix.CleanMD5SHA1(romNode.Attributes.GetNamedItem("sha1"), 40),
                                  MD5 = VarFix.CleanMD5SHA1(romNode.Attributes.GetNamedItem("md5"), 32),
                                  Merge = VarFix.CleanFullFileName(romNode.Attributes.GetNamedItem("merge")),
                                  Status = VarFix.ToLower(romNode.Attributes.GetNamedItem("status"))
                              };

            if (tRom.Size != null) tRom.FileStatusSet(FileStatus.SizeFromDAT);
            if (tRom.CRC != null) tRom.FileStatusSet(FileStatus.CRCFromDAT);
            if (tRom.SHA1 != null) tRom.FileStatusSet(FileStatus.SHA1FromDAT);
            if (tRom.MD5 != null) tRom.FileStatusSet(FileStatus.MD5FromDAT);

            tGame.ChildAdd(tRom);
        }
        // find all of the files that we think we have that match the needed CRC and Size.
        public static void RomSearchFindMatchingFiles(RvFile tRom, List<RvFile> lstFiles, out int startIndex, out int length)
        {
            int intIndex;
            int intRes = RomSearchCRCSize(tRom, lstFiles, out intIndex);
            startIndex = intIndex;

            while (intRes == 0)
            {
                intIndex++;
                intRes = intIndex < lstFiles.Count ? RomSortCRCSizeFunc(lstFiles[intIndex], tRom) : 1;
            }
            length = intIndex - startIndex;
        }
        private static int RomSearchSHA1CHD(RvFile tRom, List<RvFile> lstFiles, out int index)
        {
            if (lstFiles.Count == 0)
            {
                index = 0;
                return -1;
            }

            // this one below method will always return the first item in a list if there is more than one matching result.
            int intBottom = -1;
            int intTop = lstFiles.Count - 1;

            while (intBottom + 1 < intTop)
            {
                int intMid = (intBottom + intTop + 1) / 2;

                int intRes = RomSortSHA1CHDFunc(lstFiles[intMid], tRom);
                if (intRes >= 0)
                    intTop = intMid;
                else
                    intBottom = intMid;

            }
            intBottom++;
            index = intBottom;
            return RomSortSHA1CHDFunc(lstFiles[intBottom], tRom);
        }
        private static int RomSortCRCSizeFunc(RvFile a, RvFile b)
        {
            int retv = ArrByte.iCompare(a.CRC, b.CRC);

            if (retv == 0)
                retv = ULong.iCompare(a.Size, b.Size);

            return retv;
        }
        private static void CheckADir(RvDir dbDir, bool report)
        {
            if (_cacheSaveTimer.Elapsed.TotalMinutes > Settings.CacheSaveTimePeriod)
            {
                _bgw.ReportProgress(0, "Saving Cache");
                DB.Write();
                _bgw.ReportProgress(0, "Saving Cache Complete");
                _cacheSaveTimer.Reset();
                _cacheSaveTimer.Start();
            }

            string fullDir = dbDir.FullName;
            if (report)
                _bgw.ReportProgress(0, new bgwText2(fullDir));

            DatStatus chechingDatStatus = dbDir.IsInToSort ? DatStatus.InToSort : DatStatus.NotInDat;

            // this is a temporary rvDir structure to store the data about the actual directory/files we are scanning
            // we will first populate this variable with the real file data from the directory, and then compare it
            // with the data in dbDir.
            RvDir fileDir = null;


            Debug.WriteLine(fullDir);

            FileType ft = dbDir.FileType;

            #region "Populate fileDir"

            // if we are scanning a ZIP file then populate scanDir from the ZIP file
            switch (ft)
            {
                case FileType.Zip:
                    {
                        fileDir = new RvDir(ft);

                        // open the zip file
                        ZipFile checkZ = new ZipFile();

                        ZipReturn zr = checkZ.ZipFileOpen(fullDir, dbDir.TimeStamp, true);

                        if (zr == ZipReturn.ZipGood)
                        {
                            dbDir.ZipStatus = checkZ.ZipStatus;

                            // to be Scanning a ZIP file means it is either new or has changed.
                            // as the code below only calls back here if that is true.
                            //
                            // Level1: Only use header CRC's
                            // Just get the CRC for the ZIP headers.
                            //
                            // Level2: Fully checksum changed only files
                            // We know this file has been changed to do a full checksum scan.
                            //
                            // Level3: Fully checksum everything
                            // So do a full checksum scan.
                            if (EScanLevel == eScanLevel.Level2 || EScanLevel == eScanLevel.Level3)
                                checkZ.DeepScan();

                            // add all of the file information from the zip file into scanDir
                            for (int i = 0; i < checkZ.LocalFilesCount(); i++)
                            {
                                RvFile tFile = new RvFile(DBTypeGet.FileFromDir(ft))
                                                   {
                                                       Name = checkZ.Filename(i),
                                                       ZipFileIndex = i,
                                                       ZipFileHeaderPosition = checkZ.LocalHeader(i),
                                                       Size = checkZ.UncompressedSize(i),
                                                       CRC = checkZ.CRC32(i)
                                                   };
                                // all 3 levels read the CRC from the ZIP header
                                tFile.SetStatus(chechingDatStatus, GotStatus.Got);
                                tFile.FileStatusSet(FileStatus.SizeFromHeader | FileStatus.CRCFromHeader);

                                // if we are in level 2 or level 3 then do a full CheckSum Scan.
                                if (EScanLevel == eScanLevel.Level2 || EScanLevel == eScanLevel.Level3)
                                {
                                    // DeepScan will return ZipReturn.ZipCRCDecodeError if the headers CRC and 
                                    // the actual CRC do not match.
                                    // So we just need to set the MD5 and SHA1 from the ZIP file.
                                    zr = checkZ.FileStatus(i);
                                    if (zr == ZipReturn.ZipUntested)
                                    {
                                        _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir + " : " + checkZ.Filename(i)));
                                    }
                                    else if (zr != ZipReturn.ZipGood)
                                    {
                                        _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir + " : " + checkZ.Filename(i)));
                                        tFile.GotStatus = GotStatus.Corrupt;
                                    }
                                    else
                                    {
                                        tFile.MD5 = checkZ.MD5(i);
                                        tFile.SHA1 = checkZ.SHA1(i);
                                        tFile.FileStatusSet(FileStatus.SizeVerified | FileStatus.CRCVerified | FileStatus.SHA1Verified | FileStatus.MD5Verified);
                                    }
                                }

                                fileDir.ChildAdd(tFile);
                            }
                        }
                        else if (zr == ZipReturn.ZipFileLocked)
                        {
                            _bgw.ReportProgress(0, new bgwShowError(fullDir, "Zip File Locked"));
                            dbDir.TimeStamp = 0;
                            dbDir.GotStatus = GotStatus.FileLocked;
                        }
                        else
                        {
                            _bgw.ReportProgress(0, new bgwShowCorrupt(zr, fullDir));
                            dbDir.GotStatus = GotStatus.Corrupt;
                        }
                        checkZ.ZipFileClose();
                    }
                    break;

                case FileType.Dir:
                    {
                        fileDir = new RvDir(FileType.Dir);


                        DirectoryInfo oDir = new DirectoryInfo(fullDir);
                        DirectoryInfo[] oDirs = oDir.GetDirectories();
                        FileInfo[] oFiles = oDir.GetFiles();

                        // add all the subdirectories into scanDir 
                        foreach (DirectoryInfo dir in oDirs)
                        {
                            RvBase tDir = new RvDir(FileType.Dir)
                                              {
                                                  Name = dir.Name,
                                                  TimeStamp = dir.LastWriteTime,
                                              };
                            tDir.SetStatus(chechingDatStatus, GotStatus.Got);
                            fileDir.ChildAdd(tDir);
                        }

                        // add all the files into scanDir
                        foreach (FileInfo oFile in oFiles)
                        {
                            // if we find any zip files add them as zip files.
                            string fExt = Path.GetExtension(oFile.Name);
                            switch (fExt.ToLower())
                            {
                                case ".zip":
                                    {
                                        RvDir tGame = new RvDir(FileType.Zip)
                                                          {
                                                              Name = Path.GetFileNameWithoutExtension(oFile.Name),
                                                              TimeStamp = oFile.LastWriteTime,
                                                          };
                                        tGame.SetStatus(chechingDatStatus, GotStatus.Got);
                                        fileDir.ChildAdd(tGame);
                                    }
                                    break;
                                default:
                                    {
                                        string fName = oFile.Name;
                                        if (fName == "__RomVault.tmp")
                                        {
                                            File.Delete(oFile.FullName);
                                            continue;
                                        }

                                        // Scanning a file
                                        //
                                        // Level1 & 2 : (are the same for files) Fully checksum changed only files
                                        // Here we are just getting the TimeStamp of the File, and later
                                        // if the TimeStamp was not matched we will have to read the files CRC, MD5 & SHA1
                                        //
                                        // Level3: Fully checksum everything
                                        // Get everything about the file right here so
                                        // read CRC, MD5 & SHA1


                                        // add all the files in the sub-directory to scanDir
                                        RvFile tFile = new RvFile(FileType.File)
                                                           {
                                                               Name = fName,
                                                               Size = (ulong)oFile.Length,
                                                               TimeStamp = oFile.LastWriteTime
                                                           };

                                        tFile.FileStatusSet(FileStatus.SizeVerified);

                                        int errorCode = CHD.CheckFile(oFile, out tFile.SHA1CHD, out tFile.MD5CHD, out tFile.CHDVersion);

                                        if (errorCode == 0)
                                        {
                                            if (tFile.SHA1CHD != null) tFile.FileStatusSet(FileStatus.SHA1CHDFromHeader);
                                            if (tFile.MD5CHD != null) tFile.FileStatusSet(FileStatus.MD5CHDFromHeader);

                                            tFile.SetStatus(chechingDatStatus, GotStatus.Got);

                                            // if we are scanning at Level3 then we get all the info here
                                            if (EScanLevel == eScanLevel.Level3)
                                            {
                                                DeepScanFile(fullDir, tFile);
                                                ChdManCheck(fullDir, tFile);
                                            }
                                        }
                                        else if (errorCode == 32)
                                        {
                                            tFile.GotStatus = GotStatus.FileLocked;
                                            _bgw.ReportProgress(0, new bgwShowError(fullDir, "File Locked"));
                                        }
                                        else
                                        {
                                            string filename = Path.Combine(fullDir, tFile.Name);
                                            ReportError.Show("File: " + filename + " Error: " + new Win32Exception(errorCode).Message + ". Scan Aborted.");
                                            _fileErrorAbort = true;
                                            return;
                                        }
                                        fileDir.ChildAdd(tFile);
                                    }
                                    break;
                            }
                        }
                    }
                    break;
                default:
                    ReportError.SendAndShow("Un supported file type in CheckADir " + ft);
                    break;
            }
            #endregion

            if (fileDir == null)
            {
                ReportError.SendAndShow("Unknown Reading File Type in Dir Scanner");
                return;
            }

            if (report)
            {
                _bgw.ReportProgress(0, new bgwSetRange2(fileDir.ChildCount - 1));

                _bgw.ReportProgress(0, new bgwRange2Visible(true));
            }

            if (!DBTypeGet.isCompressedDir(ft) && _bgw.CancellationPending) return;

            Compare(dbDir, fileDir, report, true);
        }
        private static void RomSortSHA1CHD(int intBase, int intTop, List<RvFile> lstFiles)
        {
            if ((intTop - intBase) <= 1) return;
            int intMiddle = (intTop + intBase) / 2;

            if ((intMiddle - intBase) > 1)
                RomSortSHA1CHD(intBase, intMiddle, lstFiles);

            if ((intTop - intMiddle) > 1)
                RomSortSHA1CHD(intMiddle, intTop, lstFiles);

            int intBottomSize = intMiddle - intBase;
            int intTopSize = intTop - intMiddle;

            RvFile[] lstBottom = new RvFile[intBottomSize];
            RvFile[] lstTop = new RvFile[intTopSize];

            for (int intloop = 0; intloop < intBottomSize; intloop++)
                lstBottom[intloop] = lstFiles[intBase + intloop];

            for (int intloop = 0; intloop < intTopSize; intloop++)
                lstTop[intloop] = lstFiles[intMiddle + intloop];

            int intBottomCount = 0;
            int intTopCount = 0;
            int intCount = intBase;

            while (intBottomCount < intBottomSize && intTopCount < intTopSize)
            {
                if (RomSortSHA1CHDFunc(lstBottom[intBottomCount], lstTop[intTopCount]) < 1)
                {
                    lstFiles[intCount] = lstBottom[intBottomCount];
                    intCount++;
                    intBottomCount++;
                }
                else
                {
                    lstFiles[intCount] = lstTop[intTopCount];
                    intCount++;
                    intTopCount++;
                }
            }

            while (intBottomCount < intBottomSize)
            {
                lstFiles[intCount] = lstBottom[intBottomCount];
                intCount++;
                intBottomCount++;
            }
            while (intTopCount < intTopSize)
            {
                lstFiles[intCount] = lstTop[intTopCount];
                intCount++;
                intTopCount++;
            }
        }
        private static bool IschdmanScanned(RvFile tFile)
        {
            //if (!tFile.FileStatusIs(FileStatus.SHA1CHDFromHeader))
            //    return true;

            if (tFile.GotStatus == GotStatus.Corrupt)
                return true;

            return tFile.FileStatusIs(FileStatus.SHA1CHDVerified);
        }
        private static int RomSortSHA1CHDFunc(RvFile a, RvFile b)
        {
            int retv = ArrByte.iCompare(a.SHA1CHD, b.SHA1CHD);

            return retv;
        }
        private static void ChdManCheck(string directory, RvFile tFile)
        {
            string filename = Path.Combine(directory, tFile.Name);

            if (!tFile.FileStatusIs(FileStatus.SHA1CHDFromHeader)) return;
            _bgw.ReportProgress(0, new bgwText2(filename));

            string error;
            CHD.CHDManCheck res = CHD.ChdmanCheck(filename, _bgw, out error);
            switch (res)
            {
                case CHD.CHDManCheck.Good:
                    tFile.FileStatusSet(FileStatus.SHA1CHDVerified);
                    return;
                case CHD.CHDManCheck.Corrupt:
                    _bgw.ReportProgress(0, new bgwShowError(filename, error));
                    tFile.GotStatus = GotStatus.Corrupt;
                    return;
                case CHD.CHDManCheck.CHDReturnError:
                case CHD.CHDManCheck.CHDUnknownError:
                    _bgw.ReportProgress(0, new bgwShowError(filename, error));
                    return;
                case CHD.CHDManCheck.ChdmanNotFound:
                    return;
                case CHD.CHDManCheck.CHDNotFound:
                    ReportError.Show("File: " + filename + " Error: Not Found scan Aborted.");
                    _fileErrorAbort = true;
                    return;
                default:
                    ReportError.UnhandledExceptionHandler(error);
                    return;
            }
        }
        private static void LoadRomFromDat(ref RvDir tGame, XmlNode romNode)
        {
            if (romNode.Attributes == null)
                return;

            XmlNode name = romNode.Attributes.GetNamedItem("name");
            string loadflag = VarFix.String(romNode.Attributes.GetNamedItem("loadflag"));
            if (name != null)
            {
                RvFile tRom = new RvFile(FileType.ZipFile)
                                     {
                                         Name = VarFix.CleanFullFileName(name),
                                         Size = VarFix.ULong(romNode.Attributes.GetNamedItem("size")),
                                         CRC = VarFix.CleanMD5SHA1(romNode.Attributes.GetNamedItem("crc"), 8),
                                         SHA1 = VarFix.CleanMD5SHA1(romNode.Attributes.GetNamedItem("sha1"), 40),
                                         Status = VarFix.ToLower(romNode.Attributes.GetNamedItem("status")),

                                         Dat = tGame.Dat
                                     };

                if (tRom.Size != null) tRom.FileStatusSet(FileStatus.SizeFromDAT);
                if (tRom.CRC != null) tRom.FileStatusSet(FileStatus.CRCFromDAT);
                if (tRom.SHA1 != null) tRom.FileStatusSet(FileStatus.SHA1FromDAT);

                _indexContinue = tGame.ChildAdd(tRom);
            }
            else if (loadflag.ToLower() == "continue")
            {
                RvFile tZippedFile = (RvFile)tGame.Child(_indexContinue);
                tZippedFile.Size += VarFix.ULong(romNode.Attributes.GetNamedItem("size"));
            }
        }
        //Raw Copy
        // Returns True is a raw copy can be used
        // Returns False is a full recompression is required
        private static bool RawCopy(RvFile fileIn, RvFile fileOut, bool forceRaw)
        {
            if (fileIn == null || fileOut == null)
                return false;

            if ((fileIn.FileType != FileType.ZipFile) || (fileOut.FileType != FileType.ZipFile))
                return false;

            if (fileIn.Parent == null)
                return false;

            if (forceRaw) return true;

            bool trrntzipped = (fileIn.Parent.ZipStatus & ZipStatus.TrrntZip) == ZipStatus.TrrntZip;

            bool deepchecked = fileIn.FileStatusIs(FileStatus.SHA1Verified) && fileIn.FileStatusIs(FileStatus.MD5Verified);

            switch (Settings.FixLevel)
            {
                case eFixLevel.TrrntZipLevel1:
                    return trrntzipped;
                case eFixLevel.TrrntZipLevel2:
                    return trrntzipped && deepchecked;
                case eFixLevel.TrrntZipLevel3:
                    return false;

                case eFixLevel.Level1:
                    return true;
                case eFixLevel.Level2:
                    return deepchecked;
                case eFixLevel.Level3:
                    return false;
            }

            return false;
        }
Exemple #31
0
        private static ReturnCode FixFilePreCheckFixFile(RvFile fixFile)
        {
            string fileName = fixFile.FullName;

            // find all files in the DB with this name
            // there could be another file if:
            // there is a wrong file with the same name that can just be deleted
            // there is a wrong file with the same name that needs moved to ToSort
            // there is a wrong file with the same name that is needed to fix another file
            List<RvBase> testList = new List<RvBase>();

            RvDir parent = fixFile.Parent;
            int index;
            // start by finding the first file in the DB. (This should always work, as it will at least find the current file that CanBeFixed
            if (parent.ChildNameSearch(fixFile, out index) != 0)
            {
                ReportError.Show("Logic error trying to find the file we are fixing " + fileName);
                return ReturnCode.LogicError;
            }
            testList.Add(parent.Child(index++));

            // now loop to see if there are any more files with the same name. (This is a case insensative compare)                        
            while (index < parent.ChildCount && DBHelper.CompareName(fixFile, parent.Child(index)) == 0)
            {
                testList.Add(parent.Child(index));
                index++;
            }

            // if we found more that one file in the DB then we need to process the incorrect file first.
            if (testList.Count > 1)
            {
                foreach (RvBase testChild in testList)
                {
                    if (testChild == fixFile)
                        continue;

                    if (testChild.DatStatus != DatStatus.NotInDat)
                    {
                        ReportError.Show(Resources.FixFiles_FixFile_Trying_to_fix_a_file_that_already_exists + fileName);
                        return ReturnCode.LogicError;
                    }

                    RvFile testFile = testChild as RvFile;
                    if (testFile == null)
                    {
                        ReportError.Show("Did not find a file logic error while fixing duplicate named file. in FixFile");
                        return ReturnCode.LogicError;
                    }

                    switch (testFile.RepStatus)
                    {
                        case RepStatus.Delete:
                            {
                                ReturnCode ret = FixFileDelete(testFile);
                                if (ret != ReturnCode.Good)
                                    return ret;
                                break;
                            }
                        case RepStatus.MoveToSort:
                            {
                                ReturnCode ret = FixFileMoveToSort(testFile);
                                if (ret != ReturnCode.Good)
                                    return ret;
                                break;
                            }
                        case RepStatus.MoveToCorrupt:
                            {
                                ReturnCode ret = FixFileMoveToCorrupt(testFile);
                                if (ret != ReturnCode.Good)
                                    return ret;
                                break;
                            }
                        case RepStatus.NeededForFix:
                        case RepStatus.Rename:
                            {
                                // so now we have found the file with the same case insensative name and can rename it to something else to get it out of the way for now.
                                // need to check that the .tmp filename does not already exists.
                                File.SetAttributes(testChild.FullName, FileAttributes.Normal);
                                File.Move(testChild.FullName, testChild.FullName + ".tmp");

                                if (!parent.FindChild(testChild, out index))
                                {
                                    ReportError.Show("Unknown file status in Matching File found of " + testFile.RepStatus);
                                    return ReturnCode.LogicError;
                                }
                                parent.ChildRemove(index);
                                testChild.Name = testChild.Name + ".tmp";
                                parent.ChildAdd(testChild);
                                break;
                            }
                        default:
                            {
                                ReportError.Show("Unknown file status in Matching File found of " + testFile.RepStatus);
                                return ReturnCode.LogicError;
                            }
                    }
                }
            }
            else
            {
                // if there is only one file in the DB then it must be the current file that CanBeFixed
                if (testList[0] != fixFile)
                {
                    ReportError.Show("Logic error trying to find the file we are fixing " + fileName + " DB found file does not match");
                    return ReturnCode.LogicError;
                }
            }
            return ReturnCode.Good;
        }