예제 #1
0
        /// <summary>
        /// this is usually only used for remote clients; standalone clients are patched with a windows installer program
        /// </summary>
        private static void CheckForPatches()
        {
            FSplashScreen.ProgressText = "Running checks that are specific to Remote Installation...";

            // todo: check whether the user has SYSADMIN rights; should not be required
            // todo: check whether the user has write access to the bin directory
            // check whether the user has access to the server and the Petra patches directory
            if ((TClientSettings.Petra_Path_RemotePatches.Length > 0)
                && !(TClientSettings.Petra_Path_RemotePatches.ToLower().StartsWith("http://")
                     || TClientSettings.Petra_Path_RemotePatches.ToLower().StartsWith("https://"))
                && !System.IO.Directory.Exists(TClientSettings.Petra_Path_RemotePatches))
            {
                FSplashScreen.ShowMessageBox(
                    String.Format(
                        Catalog.GetString(
                            "Please make sure that you have logged in to your network drive\nand can access the directory\n{0}\nIf this is the case and you still get this message,\nyou might use an IP address rather than a hostname for the server.\nPlease ask your local System Administrator for help."),
                        TClientSettings.Petra_Path_RemotePatches),
                    Catalog.GetString("Cannot check for patches"));
            }

            // check whether there is a patch available; if this is a remote version, try to download a patch from the server
            TPatchTools patchTools = new TPatchTools(Path.GetFullPath(TClientSettings.Petra_Path_Bin + Path.DirectorySeparatorChar + ".."),
                TClientSettings.Petra_Path_Bin,
                TPatchTools.OPENPETRA_VERSIONPREFIX,
                TClientSettings.PathTemp,
                "",
                TClientSettings.Petra_Path_Patches,
                TClientSettings.Petra_Path_RemotePatches);

            string PatchStatusMessage;

            // TODO: run this only if necessary. seem adding cost centre does not update the cache?
            TDataCache.ClearAllCaches();

            if (patchTools.CheckForRecentPatch(false, out PatchStatusMessage))
            {
                // todo: display a list of all patches that will be installed? or confusing with different builds?
                if (FSplashScreen.ShowMessageBox(String.Format(Catalog.GetString("There is a new patch available: {0}" +
                                ".\r\nThe currently installed version is {1}" +
                                ".\r\nThe patch will be installed to directory '{2}'.\r\nDo you want to install now?"),
                            patchTools.GetLatestPatchVersion(), patchTools.GetCurrentPatchVersion(), TClientSettings.Petra_Path_Bin),
                        String.Format(Catalog.GetString("Install new OpenPetra patch")), MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                        MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                {
                    // reset the caches in IsolatedStorage. This can help if things have changed drastically in the database
                    // TODO: run this also after the software has been reinstalled with the InnoSetup installer? Remember the current patch number in the IsolatedStorage?
                    TDataCache.ClearAllCaches();

                    // create the temp directory; using the Petra tmp directory, so that we don't need to change the drive in the batch file
                    string TempPath = TClientSettings.PathTemp + Path.DirectorySeparatorChar + "petrapatch";
                    Directory.CreateDirectory(TempPath);

                    // check for newer patchtool
                    patchTools.CopyLatestPatchProgram(TempPath);

                    string PatchToolExe = TempPath + Path.DirectorySeparatorChar + "Ict.Tools.PtchTool.exe";

                    if (!File.Exists(PatchToolExe))
                    {
                        TLogging.Log("cannot find file " + PatchToolExe);
                    }

                    // need to stop petra client, start the patch in temppath, restart Petra client
                    Process PatchProcess = new System.Diagnostics.Process();
                    PatchProcess.EnableRaisingEvents = false;
                    PatchProcess.StartInfo.FileName = PatchToolExe;
                    PatchProcess.StartInfo.Arguments = "-action:patchRemote " +
                                                       "-ClientConfig:\"" + Path.GetFullPath(
                        TAppSettingsManager.ConfigFileName) + "\" " +
                                                       "-OpenPetra.Path.Patches:\"" + Path.GetFullPath(
                        TClientSettings.Petra_Path_Bin + "/../patches30") + "\" " +
                                                       "-OpenPetra.PathTemp:\"" + Path.GetFullPath(
                        TClientSettings.Petra_Path_Bin + "/../tmp30") + "\" " +
                                                       "-OpenPetra.Path:\"" + Path.GetFullPath(
                        TClientSettings.Petra_Path_Bin + Path.DirectorySeparatorChar + "..") + "\" " +
                                                       "-OpenPetra.Path.Bin:\"" + Path.GetFullPath(
                        TClientSettings.Petra_Path_Bin) + "\"";
                    PatchProcess.Start();

                    // Application stops here !!!
                    Environment.Exit(0);
                }
            }
            else
            {
                if (PatchStatusMessage != String.Empty)
                {
                    FSplashScreen.ShowMessageBox(PatchStatusMessage, "");
                }
            }
        }
예제 #2
0
        private void ApplyPatchRecursively(String APatchRootDirectory, String APatchDirectory)
        {
            string[] directories = System.IO.Directory.GetDirectories(APatchDirectory);

            foreach (string dir in directories)
            {
                ApplyPatchRecursively(APatchRootDirectory, dir);
            }

            TPatchTools patch = new TPatchTools();
            string[] files = System.IO.Directory.GetFiles(APatchDirectory);

            foreach (string filename in files)
            {
                // what to do with the file: add, remove, patch
                string action;
                String TargetFile;

                // find a match with the registered File Patterns
                if ((!GetMatch(filename.Substring(APatchRootDirectory.Length + 1), out action, out TargetFile)))
                {
                    throw new Exception("cannot find a destination path for file " + filename.Substring(APatchRootDirectory.Length + 1));
                }

                // make sure that the path exists
                string TargetPath = Path.GetDirectoryName(TargetFile);

                if (!Directory.Exists(TargetPath))
                {
                    Directory.CreateDirectory(TargetPath);
                }

                // Console.WriteLine(filename + ' ' + TargetFile);
                if (action == "new")
                {
                    if (System.IO.File.Exists(TargetFile))
                    {
                        // prepare for undo; make a copy of the original file
                        System.IO.File.Copy(TargetFile, TargetFile + ".bak", true);
                        File.Delete(TargetFile);
                    }

                    // unzip the file
                    BZip2.Decompress(System.IO.File.OpenRead(filename), System.IO.File.OpenWrite(TargetFile), true);
                }
                else if ((action == "patch") && File.Exists(TargetFile))
                {
                    try
                    {
                        // safety copy
                        System.IO.File.Copy(TargetFile, TargetFile + ".bak", true);

                        // apply patch
                        if (System.IO.File.Exists(TargetFile + ".new"))
                        {
                            System.IO.File.Delete(TargetFile + ".new");
                        }

                        patch.ApplyPatch(TargetFile, TargetFile + ".new", filename);

                        // remove original, rename file
                        if (System.IO.File.Exists(TargetFile + ".new"))
                        {
                            if (System.IO.File.Exists(TargetFile))
                            {
                                System.IO.File.Delete(TargetFile);
                            }

                            System.IO.File.Move(TargetFile + ".new", TargetFile);
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("problem patching file " + TargetFile + ": " + e.Message);
                    }
                }
                else if (action == "rem")
                {
                    if (System.IO.File.Exists(TargetFile))
                    {
                        // safety copy
                        System.IO.File.Copy(TargetFile, TargetFile + ".bak");

                        // remove file
                        System.IO.File.Delete(TargetFile);
                    }
                }
                else if (action == "skip")
                {
                    // skip server files on a remote system
                }
            }
        }
예제 #3
0
        private static void CreateDiffFiles(String ATmpDirectory,
            String ARootPatchDirectory,
            String AOldDirectory,
            String ANewDirectory,
            String ARecursiveSubDir)
        {
            string OldDirectory = AOldDirectory + '/' + ARecursiveSubDir;
            string NewDirectory = ANewDirectory + '/' + ARecursiveSubDir;
            string PatchDirectory = ARootPatchDirectory + '/' + ARecursiveSubDir;

            if (!Directory.Exists(PatchDirectory))
            {
                Directory.CreateDirectory(PatchDirectory);
            }

            if (!Directory.Exists(OldDirectory))
            {
                Directory.CreateDirectory(OldDirectory);
            }

            string[] directories = Directory.GetDirectories(NewDirectory);

            foreach (string dir in directories)
            {
                CreateDiffFiles(ATmpDirectory,
                    ARootPatchDirectory,
                    AOldDirectory, ANewDirectory, dir.Substring(ANewDirectory.Length + 1));
            }

            // compare the files file by file
            TLogging.Log("enter directory " + OldDirectory, TLoggingType.ToConsole);
            string[] files = System.IO.Directory.GetFiles(OldDirectory);

            foreach (string filenameLoop in files)
            {
                bool OldPatchFileReused = false;
                string filename = Path.GetFileName(filenameLoop);

                if (System.IO.File.Exists(NewDirectory + '/' + filename))
                {
                    TPatchTools patch = new TPatchTools();

                    // compare if files are actually different
                    if (!patch.IsSame(filenameLoop, NewDirectory + '/' + Path.GetFileName(filename)))
                    {
                        // create binary diff
                        if (!Directory.Exists(PatchDirectory))
                        {
                            Directory.CreateDirectory(PatchDirectory);
                        }

                        string OldPatchFile = ARootPatchDirectory + "bak" + PatchDirectory.Substring(ARootPatchDirectory.Length) + '/' +
                                              Path.GetFileName(filename) + ".patch";

                        if (System.IO.File.Exists(OldPatchFile))
                        {
                            // could reuse, if checksum of the result is the same
                            TPatchFileInfo OldPatchFileInfo;
                            patch.ReadHeader(OldPatchFile, out OldPatchFileInfo);

                            if (patch.CheckMd5Sum(NewDirectory + '/' + Path.GetFileName(filename),
                                    OldPatchFileInfo.NewMd5sum) && patch.CheckMd5Sum(filenameLoop, OldPatchFileInfo.OldMd5sum))
                            {
                                // found a match, so no need for recreating the patch file; just copy it
                                TLogging.Log("reusing diff " + OldPatchFile, TLoggingType.ToConsole);
                                System.IO.File.Copy(OldPatchFile, PatchDirectory + '/' + Path.GetFileName(filename) + ".patch");
                                OldPatchFileReused = true;
                            }
                        }

                        if (!OldPatchFileReused)
                        {
                            TLogging.Log("create diff " + PatchDirectory + '/' + Path.GetFileName(filename), TLoggingType.ToConsole);
                            patch.CreateDiff(filenameLoop, NewDirectory + '/' + Path.GetFileName(filename), PatchDirectory + '/' +
                                Path.GetFileName(filename) + ".patch");
                        }

                        // if this is a file required for the patch program, include the new version
                        if ((Path.GetFileName(filename) == "Ict.Common.dll") || (Path.GetFileName(filename) == "Ict.Common.IO.dll")
                            || (Path.GetFileName(filename) == "ICSharpCode.SharpZipLib.dll")
                            || (Path.GetFileName(filename).ToLower() == "Ict.Tools.PatchTool.exe".ToLower()))
                        {
                            // don't compress here:
                            // the whole patch directory is zipped anyways in the end;
                            // and it is easier to extract before running the patch
                            System.IO.File.Copy(NewDirectory + '/' + Path.GetFileName(filename), PatchDirectory + '/' + Path.GetFileName(
                                    filename), true);
                        }
                    }
                }
            }

            // add new files (zip them)
            files = System.IO.Directory.GetFiles(NewDirectory);

            foreach (string filename in files)
            {
                if (!System.IO.File.Exists(OldDirectory + '/' + Path.GetFileName(filename)))
                {
                    TLogging.Log("zip a new file " + NewDirectory + '/' + Path.GetFileName(filename), TLoggingType.ToConsole);

                    if (!Directory.Exists(PatchDirectory))
                    {
                        Directory.CreateDirectory(PatchDirectory);
                    }

                    try
                    {
                        BZip2.Compress(System.IO.File.OpenRead(NewDirectory + '/' + Path.GetFileName(filename)),
                            System.IO.File.OpenWrite(PatchDirectory + '/' + Path.GetFileName(filename) + ".new"), true, 4096);
                    }
                    catch (Exception)
                    {
                        throw new Exception("Cannot write to file " + PatchDirectory + '/' + Path.GetFileName(filename) + ".new");
                    }
                }
            }

            // tell to remove files
            files = System.IO.Directory.GetFiles(OldDirectory);

            foreach (string filename in files)
            {
                if (!System.IO.File.Exists(NewDirectory + '/' + Path.GetFileName(filename)))
                {
                    TLogging.Log("file removed: " + OldDirectory + '/' + Path.GetFileName(filename), TLoggingType.ToConsole);
                    FileStream stream = System.IO.File.OpenWrite(PatchDirectory + '/' + Path.GetFileName(filename) + ".rem");
                    stream.Close();
                }
            }

            // todo: something about changes to config files? xml file with instructions?
            // todo: check if all files can be matched when installing the patch
        }