Пример #1
0
 public DefaultPatcher(IClientProfile clientProfile, IServerProfile serverProfile, PatcherContext patcherContext)
 {
     ClientProfile  = clientProfile;
     ServerProfile  = serverProfile;
     PatcherContext = patcherContext;
     PatcherType    = DefaultPatcherTypes.Default;
 }
Пример #2
0
 /// <summary>
 ///     Creates a task which represent an individual patch operation
 /// </summary>
 /// <param name="clientProfile"></param>
 /// <param name="patchInfo"></param>
 /// <param name="officialPatchInfo"></param>
 /// <param name="patcherContext"></param>
 public PatchTask(PatcherContext patcherContext, IClientProfile clientProfile, PatchInfo patchInfo, OfficialPatchInfo officialPatchInfo)
 {
     _patcherContext   = patcherContext;
     _clientProfile    = clientProfile;
     PatchInfo         = patchInfo;
     OfficialPatchInfo = officialPatchInfo;
 }
Пример #3
0
 public PatchDownloader(List <Patch> patches, IClientProfile clientProfile,
                        PatcherContext patcherContext)
 {
     _patches        = patches;
     _clientProfile  = clientProfile;
     _patcherContext = patcherContext;
     _queueManager   = new QueueManager(_patcherContext);
 }
Пример #4
0
 /// <summary>
 ///     Creates a download queue but does not initialize it
 /// </summary>
 /// <param name="patcherContext"></param>
 /// <param name="patchInfos"></param>
 /// <param name="officialPatchInfo"></param>
 public DownloadQueue(PatcherContext patcherContext, IClientProfile clientProfile, List <PatchInfo> patchInfos, OfficialPatchInfo officialPatchInfo)
 {
     _patcherContext    = patcherContext;
     _clientProfile     = clientProfile;
     _patchInfos        = patchInfos;
     _patchTasks        = new List <PatchTask>();
     _officialPatchInfo = officialPatchInfo;
 }
Пример #5
0
 /// <summary>
 ///     Creates a new instance of PatcherDownloader that accepts a PatchSequence
 /// </summary>
 /// <param name="patchSequence">PatchSequence representing a collection of patches</param>
 /// <param name="officialPatchInfo"></param>
 /// <param name="clientProfile"></param>
 public PatchDownloader(PatcherContext patcherContext, PatchSequence patchSequence, OfficialPatchInfo officialPatchInfo, IClientProfile clientProfile)
 {
     Patches            = new List <PatchInfo>();
     _patcherContext    = patcherContext;
     _officialPatchInfo = officialPatchInfo;
     _clientProfile     = clientProfile;
     Patches.AddRange(patchSequence.Patches);
 }
Пример #6
0
        public override async Task <bool> CheckForUpdates()
        {
            if (ClientProfile == null)
            {
                return(false);
            }
            if (ServerProfile == null)
            {
                return(false);
            }

            // Should never hit, earlier logic shouldn't even call the function
            if (!ServerProfile.IsOfficial)
            {
                return(false);
            }

            if (ClientProfile.Localization != ClientLocalization.Japan &&
                ClientProfile.Localization != ClientLocalization.JapanHangame)
            {
                return(false);
            }

            PatcherContext.SetPatcherState(true);

            PatcherContext.UpdateMainProgress("Checking for updates...", "", 0, true, true);

            _officialPatchInfo = OfficialPatchInfo.Parse(MabiVersion.Versions
                                                         .Find(version => version.Name == ClientProfile.Localization).PatchUrl);

            if (int.TryParse(_officialPatchInfo["main_version"], out var versionConverted))
            {
                _remoteVersion = versionConverted;
            }

            if (_currentVersion == _remoteVersion)
            {
                PatcherContext.SetPatcherState(false);
                PatcherContext.UpdateMainProgress("", "", 0, false, false);
                return(false);
            }

            try
            {
                await Task.Run(() => _patchSequence = FindPatchSequence());
            }
            catch (PatchSequenceNotFoundException ex)
            {
                Log.Exception(ex);
                PatcherContext.SetPatcherState(false);
                PatcherContext.UpdateMainProgress("", "", 0, false, false);
                return(false);
            }

            PatcherContext.SetPatcherState(false);
            PatcherContext.UpdateMainProgress("", "", 0, false, false);
            return(true);
        }
Пример #7
0
        private async Task <List <FileDownloadInfo> > GetFileDownloadInfo()
        {
            double entries = ((ICollection)PatchData.files).Count;

            PatcherContext.UpdateMainProgress(Properties.Resources.ParsingManifest, $"0/{entries}", 0, false, true);
            var fileDownloadInfos = new List <FileDownloadInfo>();

            await Task.Delay(1);

            int entry = 0;

            // Decode filepaths into new collection
            foreach (var file in PatchData["files"])
            {
                entry++;
                PatcherContext.UpdateMainProgress(Properties.Resources.ParsingManifest, $"{entry}/{entries}", entry / entries * 100, false, true);

                var isDirectory     = false;
                var filename        = file.Name;
                var decodedFilename = DecodeFilename(filename);

                // Nexon does not intend for this file to be downloaded or this may be some other specification
                if (file.Value["objects"].Count == 0)
                {
                    Log.Info(Properties.Resources.FileWithNoObjectsIgnored, decodedFilename);
                    continue;
                }

                if (file.Value["objects"][0] == "__DIR__")
                {
                    isDirectory = true;
                }

                var fileDownloadInfo = new FileDownloadInfo(decodedFilename, file.Value["fsize"].Value,
                                                            isDirectory ? FileInfoType.Directory : FileInfoType.File);

                fileDownloadInfo.SetModifiedTimeDateTime(file.Value["mtime"].Value);

                if (isDirectory)
                {
                    continue;
                }

                for (var i = 0; i < file.Value["objects"].Count; i++)
                {
                    var filePartInfo =
                        new FilePartInfo(file.Value["objects"][i].Value, decodedFilename, file.Value["objects_fsize"][i].Value, i);
                    fileDownloadInfo.FileParts.Add(filePartInfo);
                }

                fileDownloadInfos.Add(fileDownloadInfo);
            }

            return(fileDownloadInfos);
        }
Пример #8
0
        public override async Task <bool> RepairInstall()
        {
            var shouldUpdate = await CheckForUpdatesInternal(-1, true);

            if (shouldUpdate)
            {
                return(await ApplyUpdates());
            }
            PatcherContext.SetPatcherState(false);
            PatcherContext.UpdateMainProgress("", "", 0, false, false);
            return(true);
        }
Пример #9
0
        private bool ValidateAction(bool silent = false)
        {
            if (ClientProfile == null)
            {
                if (!silent)
                {
                    PatcherContext.ShowDialog(Properties.Resources.NoProfileSelected,
                                              Properties.Resources.NoProfileSelectedMessage2);
                }

                return(true);
            }

            if (string.IsNullOrWhiteSpace(ClientProfile.Location))
            {
                if (!silent)
                {
                    PatcherContext.ShowDialog(Properties.Resources.ProfileError,
                                              string.Format(
                                                  Properties.Resources.ProfileErrorMessage,
                                                  ClientProfile.Name));
                }
                return(true);
            }

            if (!ServerProfile.IsOfficial)
            {
                if (!silent)
                {
                    PatcherContext.ShowDialog(Properties.Resources.ActionCancelled,
                                              Properties.Resources.ActionCancelledMessage);
                }
                return(true);
            }

            if (File.Exists("steam_connector_config.json"))
            {
                Log.Info("Patching for steam is not supported at this time.");
                return(true);
            }

            if (ClientLocalization.GetLocalization(ClientProfile.Localization) != "NorthAmerica")
            {
                if (!silent)
                {
                    PatcherContext.ShowDialog(Properties.Resources.UnsupportedLocalization,
                                              Properties.Resources.UnsupportedLocalizationMessage);
                }
                return(true);
            }

            return(false);
        }
Пример #10
0
        public override async Task <bool> ApplyUpdates()
        {
            PatcherContext.SetPatcherState(true);
            PatcherContext.ShowSession();

            var downloader = new PatchDownloader(PatcherContext, _patchSequence, _officialPatchInfo, ClientProfile);
            await Task.Run(() => downloader.Prepare());

            await Task.Run(() => downloader.Patch());

            WriteVersion(_remoteVersion);

            PatcherContext.SetPatcherState(false);
            PatcherContext.HideSession();
            return(true);
        }
Пример #11
0
        public override async Task <bool> CheckForUpdates()
        {
            if (ValidateAction(true))
            {
                return(false);
            }

            PatcherContext.UpdateMainProgress(Properties.Resources.Initialize, "", 0, true, true);

            var completed = "true";

            PatcherContext.SetPatcherState(true);

            PatcherContext.UpdateMainProgress(Properties.Resources.CheckingForUpdates, "", 0, true, true);

            if (!NexonApi.Instance.IsAccessTokenValid(ClientProfile.Guid))
            {
                completed = "";
                PatcherContext.RequestUserLogin(() => completed = "true", () => completed = "false");
            }

            while (completed == "")
            {
                await Task.Delay(100);
            }

            if (completed == "false")
            {
                PatcherContext.SetPatcherState(false);
                PatcherContext.UpdateMainProgress("", "", 0, false, false);
                return(false);
            }

            var result = await CheckForUpdatesInternal(ReadVersion());

            PatcherContext.SetPatcherState(false);
            PatcherContext.UpdateMainProgress("", "", 0, false, false);

            return(result);
        }
Пример #12
0
        private async Task GetManifestJson(int version)
        {
            if (version == -1)
            {
                PatcherContext.UpdateMainProgress(Properties.Resources.GettingLatestVersion, "", 0, true, true);
                _version = version = await NexonApi.Instance.GetLatestVersion();
            }

            PatcherContext.UpdateMainProgress(Properties.Resources.DownloadingManifest, "", 0, true, true);
            // Get Manifest String
            var manifestHashString = await NexonApi.Instance.GetManifestHashString();

            // Download Manifest
            var buffer = DownloadManifestBuffer(manifestHashString);

            PatcherContext.UpdateMainProgress(Properties.Resources.DecompressingManifest, "", 0, true, true);

            // Decompress Manifest and Convert to Object
            var manifestContent = ZlibStream.UncompressString(buffer);
            var data            = JsonConvert.DeserializeObject <dynamic>(manifestContent);

            PatchData = data;
        }
Пример #13
0
        public override async Task <bool> ApplyUpdates()
        {
            if (ValidateAction())
            {
                return(false);
            }

            PatcherContext.SetPatcherState(true);
            PatcherContext.ShowSession();
            PatcherContext.UpdateMainProgress(Properties.Resources.ApplyingUpdates, "", 0, true, true);

            var patchDownloader = new PatchDownloader(Patches, ClientProfile, PatcherContext);

            bool result = false;

            try
            {
                await Task.Run(() => patchDownloader.Prepare());

                result = await Task.Run(() => patchDownloader.Patch());

                await Task.Run(() => patchDownloader.Cleanup());
            }
            catch (Exception ex)
            {
                Log.Exception(ex, "Failed to patch!");
            }
            finally
            {
                PatcherContext.UpdateMainProgress(result ? Properties.Resources.PatchComplete : Properties.Resources.PatchFailed);

                PatcherContext.SetPatcherState(false);
                PatcherContext.HideSession();
            }

            return(result);
        }
Пример #14
0
 public DownloadWrapper(Patch patch, PatcherContext patcherContext)
 {
     Patch           = patch;
     _patcherContext = patcherContext;
 }
Пример #15
0
 public NxlPatcher(IClientProfile clientProfile, IServerProfile serverProfile, PatcherContext patcherContext)
     : base(clientProfile, serverProfile, patcherContext)
 {
     PatcherType = DefaultPatcherTypes.NxLauncher;
     PatchSettingsManager.Initialize();
     PatchIgnore = new PatchIgnore(PatcherContext);
 }
Пример #16
0
        private void GetPatchList(bool overrideSettings = false)
        {
            double entries = FileDownloadInfos.Count;

            PatcherContext.UpdateMainProgress(Properties.Resources.CheckingFiles, $"0/{entries}", 0, false, true);

            var entry = 0;

            foreach (var fileDownloadInfo in FileDownloadInfos)
            {
                entry++;
                PatcherContext.UpdateMainProgress(Properties.Resources.CheckingFiles, $"{entry}/{entries}",
                                                  entry / entries * 100, false,
                                                  true);

                var filePath = fileDownloadInfo.FileName;

                if (!overrideSettings)
                {
                    if (filePath.StartsWith("package\\") &&
                        PatchSettingsManager.Instance.PatcherSettings.IgnorePackageFolder &&
                        !GetIsNewPackFile(filePath))
                    {
                        continue;
                    }
                }

                if (PatchIgnore.IgnoredFiles.Contains(filePath))
                {
                    Log.Info($"File: '{filePath}' in ignore list, file will not be patched!");
                    continue;
                }

                if (fileDownloadInfo.FileInfoType == FileInfoType.Directory)
                {
                    if (Directory.Exists(fileDownloadInfo.FileName))
                    {
                        continue;
                    }

                    Patches.Add(new Patch(fileDownloadInfo, PatchReason.DoesNotExist));
                    continue;
                }

                var  modified       = false;
                var  fileExists     = true;
                var  actualModified = new DateTime();
                var  correctSize    = true;
                long length         = 0;

                if (File.Exists(filePath))
                {
                    length         = new FileInfo(filePath).Length;
                    actualModified = File.GetLastWriteTime(filePath);
                    if (actualModified != fileDownloadInfo.LastModifiedDateTime)
                    {
                        modified = true;
                    }
                    else if (length != fileDownloadInfo.FileSize)
                    {
                        correctSize = false;
                    }
                }
                else
                {
                    fileExists = false;
                }

                if (!correctSize)
                {
                    var patch = new Patch(fileDownloadInfo, PatchReason.SizeNotMatch);
                    Patches.Add(patch);
                    Log.Info(Properties.Resources.PatchRequiredForSize, filePath,
                             patch.PatchReason.LocalizedPatchReason(), fileDownloadInfo.FileSize, length);
                    continue;
                }

                if (!fileExists)
                {
                    var patch = new Patch(fileDownloadInfo, PatchReason.DoesNotExist);
                    Patches.Add(patch);
                    Log.Info(Properties.Resources.PatchRequiredFor, filePath, patch.PatchReason.LocalizedPatchReason());
                    continue;
                }

                if (!modified)
                {
                    continue;
                }

                if (actualModified > fileDownloadInfo.LastModifiedDateTime)
                {
                    var patch = new Patch(fileDownloadInfo, PatchReason.Modified);
                    Patches.Add(patch);
                    Log.Info(Properties.Resources.PatchRequiredFor, filePath, patch.PatchReason.LocalizedPatchReason());
                }
                else
                {
                    var patch = new Patch(fileDownloadInfo);
                    Patches.Add(patch);
                    Log.Info(Properties.Resources.PatchRequiredFor, filePath, patch.PatchReason.LocalizedPatchReason());
                }
            }
        }
Пример #17
0
 public QueueManager(PatcherContext patcherContext)
 {
     _patcherContext   = patcherContext;
     _downloadWrappers = new Dictionary <string, DownloadWrapper>();
     _fileParts        = new Queue <FilePartInfo>();
 }
Пример #18
0
 public PatchIgnore(PatcherContext patcherContext)
 {
     _pluginContext = patcherContext;
 }
Пример #19
0
        private PatchSequence FindPatchSequence(int currentVersion = -1, int remoteVersion = -1)
        {
            if (currentVersion == -1)
            {
                currentVersion = _currentVersion;
            }
            if (remoteVersion == -1)
            {
                remoteVersion = _remoteVersion;
            }

            Log.Info("Attempting to find sequence from {0} to {1}", currentVersion, remoteVersion);
            var patchInfos = new List <PatchInfo>();
            var format     = "Attempting to patch from {0} to {1}. Currently checking {2}.";

            try
            {
                using (var webClient = new WebClient())
                {
                    if (currentVersion == 0)
                    {
                        PatcherContext.UpdateMainProgress(string.Format(format, 0,
                                                                        remoteVersion,
                                                                        remoteVersion), "", 0, true, true);
                        var patchInfo = GetPatchInfo(webClient, remoteVersion, $"{remoteVersion}_full.txt");
                        if (patchInfo == null)
                        {
                            throw new PatchSequenceNotFoundException(currentVersion, remoteVersion);
                        }
                        patchInfos.Add(patchInfo);
                    }
                    else
                    {
                        var fromNumber = currentVersion;
                        var toNumber   = remoteVersion;

                        while (fromNumber != toNumber)
                        {
                            PatcherContext.UpdateMainProgress(string.Format(format, currentVersion,
                                                                            remoteVersion,
                                                                            fromNumber), "", (fromNumber - (double)currentVersion / (remoteVersion - currentVersion)), true, true);
                            var patchInfo = GetPatchInfo(webClient, remoteVersion, $"{fromNumber}_to_{toNumber}.txt");

                            if (patchInfo != null)
                            {
                                patchInfos.Add(patchInfo);
                                fromNumber = toNumber;
                                toNumber  += 5;
                            }
                            else if (--toNumber == fromNumber)
                            {
                                return(FindPatchSequence(0, remoteVersion));
                            }
                        }
                    }
                }
            }
            finally
            {
                PatcherContext.UpdateMainProgress();
            }

            return(new PatchSequence(patchInfos));
        }
Пример #20
0
 public LegacyPatcher(ClientProfile clientProfile, ServerProfile serverProfile, PatcherContext patcherContext)
     : base(clientProfile, serverProfile, patcherContext)
 {
     PatcherType     = DefaultPatcherTypes.Legacy;
     _currentVersion = ReadVersion();
 }