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; }