/// <summary> /// see if any patches are missing; is there a direct line between FCurrentlyInstalledVersion and FLatestAvailablePatch? /// </summary> /// <returns>return a list of all patches that should be applied. empty list if there is a problem</returns> public SortedList CheckPatchesConsistent(SortedList AOrderedListOfAllPatches) { SortedList ResultPatchList = new SortedList(); TFileVersionInfo testPatchVersion; // get the latest patch that is available FLatestAvailablePatch = new TFileVersionInfo(FCurrentlyInstalledVersion); foreach (string patch in AOrderedListOfAllPatches.GetValueList()) { testPatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(patch); if (testPatchVersion.Compare(FLatestAvailablePatch) > 0) { FLatestAvailablePatch = testPatchVersion; } } // drop unnecessary patch files // ie. patch files leading to the same version, eg. 2.2.11-1 and 2.2.12-2 to 2.2.12-3 // we only want the biggest step testPatchVersion = new TFileVersionInfo(FCurrentlyInstalledVersion); bool patchesAvailable = true; while (patchesAvailable) { StringCollection applyingPatches = new StringCollection(); foreach (string patch in AOrderedListOfAllPatches.GetValueList()) { if (TPatchFileVersionInfo.PatchApplies(testPatchVersion, patch)) { applyingPatches.Add(patch); } } patchesAvailable = (applyingPatches.Count > 0); if (applyingPatches.Count > 0) { // see which of the applying patches takes us further string highestPatch = applyingPatches[0]; TFileVersionInfo highestPatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(highestPatch); foreach (string patch in applyingPatches) { if (TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(patch).Compare(highestPatchVersion) > 0) { highestPatch = patch; highestPatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(highestPatch); } } ResultPatchList.Add(highestPatch, highestPatch); testPatchVersion = highestPatchVersion; } } if (FLatestAvailablePatch.Compare(testPatchVersion) != 0) { // check for a generic patch file, starting from version 0.0.99.99 foreach (string patch in AOrderedListOfAllPatches.GetValueList()) { if (patch.Contains("0.0.99.99")) { testPatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(patch); ResultPatchList.Clear(); ResultPatchList.Add(patch, patch); } } } if (FLatestAvailablePatch.Compare(testPatchVersion) != 0) { TLogging.Log("missing patchfile from version " + testPatchVersion.ToString() + " to " + FLatestAvailablePatch.ToString()); return(new SortedList()); } return(ResultPatchList); }
/// <summary> /// check whether there is a patch available; if this is a remote version, try to download a patch from the server this will also get the version of the currently installed code, and the list of patches that can be installed, in local /// variables /// </summary> /// <param name="AShowStatus">Set to true to show status messages as a MessageBox /// if there is a problem, or to false to have them returned in /// <paramref name="AStatusMessage" /></param>. /// <param name="AStatusMessage">A Status Message in case there is a problem AND /// <paramref name="AShowStatus" /> is false.</param> public Boolean CheckForRecentPatch(bool AShowStatus, out string AStatusMessage) { string localname; TFileVersionInfo fileStartVersion; TFileVersionInfo filePatchVersion; string directoryListing; string searchPattern; string filesignature; AStatusMessage = ""; FListOfNewPatches = new SortedList(); // first get the version of the currently installed binaries // read from version.txt in the bin directory; it contains the currently installed version in RPM style (e.g. 3.0.0-14) if (!File.Exists(FBinPath + Path.DirectorySeparatorChar + "version.txt")) { throw new Exception(String.Format("Cannot search for new patch, since I cannot find file {0}", FBinPath + Path.DirectorySeparatorChar + "version.txt")); } StreamReader srVersion = new StreamReader(FBinPath + Path.DirectorySeparatorChar + "version.txt"); FCurrentlyInstalledVersion = new TFileVersionInfo(srVersion.ReadLine()); srVersion.Close(); if (FRemotePatchesPath.StartsWith("http://") || FRemotePatchesPath.StartsWith("https://")) { directoryListing = THTTPUtils.ReadWebsite(FRemotePatchesPath); if (directoryListing == null) { if (AShowStatus) { MessageBox.Show(String.Format(StrProblemConnecting, FRemotePatchesPath), StrProblemConnectingTitle); } else { AStatusMessage = String.Format(StrProblemConnecting, FRemotePatchesPath); } return(false); } // find all the files names that match the pattern // eg <a href="Patch2.2.7-2_2.2.8-0.zip"> searchPattern = "<a href=\""; while (directoryListing.IndexOf(searchPattern) != -1) { string filename = directoryListing.Substring( directoryListing.IndexOf(searchPattern) + searchPattern.Length, directoryListing.Substring( directoryListing.IndexOf(searchPattern) + searchPattern.Length).IndexOf('"')); directoryListing = directoryListing.Substring(directoryListing.IndexOf(searchPattern) + searchPattern.Length); // signature e.g: gr1100o.r">gr1100o.r</a> 14-Oct-2008 13:11 153K filesignature = directoryListing.Substring(0, directoryListing.IndexOf("\n")); if (filename.ToLower().StartsWith("patch") && filename.ToLower().EndsWith(".zip")) { filePatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(filename); if ((filePatchVersion.Compare(FCurrentlyInstalledVersion) > 0) && (!System.IO.File.Exists(FPatchesPath + Path.DirectorySeparatorChar + Path.GetFileName(filename)))) { string LocalName = FPatchesPath + Path.DirectorySeparatorChar + Path.GetFileName(filename); FListOfNewPatches.Add(LocalName, LocalName); } } else if (filename.Contains("Setup") && filename.EndsWith(".exe")) { // ignore setup executable } else if (filename.ToLower().EndsWith(".dll") || filename.ToLower().EndsWith(".exe")) { // download .dll/.exe files from the netpatches directory if there is no file with same date already if (System.IO.File.Exists(FPatchesPath + Path.DirectorySeparatorChar + filename + ".signature")) { StreamReader sr = new StreamReader(FPatchesPath + Path.DirectorySeparatorChar + filename + ".signature"); if (sr.ReadLine().Trim() == filesignature.Trim()) { if (System.IO.File.Exists(FPatchesPath + Path.DirectorySeparatorChar + filename + ".old") && !System.IO.File.Exists(FPatchesPath + Path.DirectorySeparatorChar + filename)) { // the file has been renamed by the patch, and needs to be reinstated System.IO.File.Move(FPatchesPath + Path.DirectorySeparatorChar + filename + ".old", FPatchesPath + Path.DirectorySeparatorChar + filename); } filename = "ALREADY_LATEST"; } sr.Close(); } if (filename != "ALREADY_LATEST") { string localFile = FPatchesPath + Path.DirectorySeparatorChar + filename; if (filename.ToLower().EndsWith(".dll") || filename.ToLower().EndsWith(".exe")) { localFile = FBinPath + Path.DirectorySeparatorChar + filename; // make backup copy of .dll/.exe if there does not already one exist; don't overwrite .orig files if (!File.Exists(localFile + ".orig")) { System.IO.File.Move(localFile, localFile + ".orig"); } } THTTPUtils.DownloadFile(FRemotePatchesPath + "/" + filename, localFile); StreamWriter sw = new StreamWriter(FPatchesPath + Path.DirectorySeparatorChar + filename + ".signature"); sw.WriteLine(filesignature); sw.Close(); } } } // todo: remove local .r files if they are not in the net-patches directory // todo: the same for *.dll and *.exe; careful: only create an .orig copy once. // todo: somehow revert to .orig dll/exe file if there is no patched file in net-patches on the server? // todo: patch has to remove dll and exe from net-patches // todo: on the server side as well; check net-patches } else if ((FRemotePatchesPath.Length > 0) && (System.IO.Directory.Exists(FRemotePatchesPath))) { // check if there are newer patches on the remote server string[] files = System.IO.Directory.GetFiles(FRemotePatchesPath, "Patch*.zip"); foreach (string filename in files) { filePatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(filename); if ((filePatchVersion.Compare(FCurrentlyInstalledVersion) > 0) && ((!System.IO.File.Exists(FPatchesPath + Path.DirectorySeparatorChar + Path.GetFileName(filename))))) { localname = FPatchesPath + Path.DirectorySeparatorChar + Path.GetFileName(filename); FListOfNewPatches.Add(localname, localname); } } } // create a list of patches that should be installed string[] patchfiles = System.IO.Directory.GetFiles(FPatchesPath, "Patch*.zip"); foreach (string filename in patchfiles) { fileStartVersion = TPatchFileVersionInfo.GetStartVersionFromDiffZipName(filename); filePatchVersion = TPatchFileVersionInfo.GetLatestPatchVersionFromDiffZipName(filename); if ((fileStartVersion.Compare(FCurrentlyInstalledVersion) >= 0) && (filePatchVersion.Compare(FCurrentlyInstalledVersion) > 0)) { FListOfNewPatches.Add(filename, filename); } } // see if any patches are missing; is there a direct line between FCurrentlyInstalledVersion and FLatestAvailablePatch? FListOfNewPatches = CheckPatchesConsistent(FListOfNewPatches); return(FListOfNewPatches.Count > 0); }
/// <summary> /// would this patch file apply to the current installed version /// </summary> /// <param name="APatchZipFile"></param> /// <returns></returns> public Boolean PatchApplies(String APatchZipFile) { return(TPatchFileVersionInfo.PatchApplies(this, APatchZipFile)); }