Beispiel #1
0
        /// <summary>
        /// Process an actual PackageManifest result, either from a list or just a standalone one.
        /// </summary>
        internal static void ProcessManifest(PackageManifest manifest, string hostUsername, string repoName)
        {
            if (manifest == null)
            {
                return;
            }

            if (string.IsNullOrEmpty(manifest.author) || !string.Equals(hostUsername, manifest.author, StringComparison.OrdinalIgnoreCase))
            {
                manifest.author = hostUsername;
            }

            manifest.repository = repoName;

            var state = GetStateForGuid(manifest.GUID);

            if (state == GuidFilterState.Blacklist)
            {
                return;
            }

            if (state == GuidFilterState.BrokenList)
            {
                manifest.m_installState = InstallState.NotWorking;
            }

            if (s_webManifests.ContainsKey(manifest.GUID))
            {
                Console.WriteLine("Duplicate web manifests found! Skipping this one: " + manifest.GUID);
                return;
            }

            s_webManifests.Add(manifest.GUID, manifest);

            if (LocalPackageManager.TryGetInstalledPackage(manifest.GUID) is PackageManifest installed)
            {
                if (installed.version == manifest.version)
                {
                    // Same version, but manifest may have been updated.
                    // Ensure the local manifest matches the web one.

                    var path = installed.IsDisabled ? Folders.MEFINO_DISABLED_FOLDER : Folders.OUTWARD_PLUGINS;
                    path += $@"\{installed.GUID}\{LocalPackageManager.PKG_MANIFEST_FILENAME}";

                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }

                    File.WriteAllText(path, manifest.ToJsonObject().ToString(true));

                    //LocalPackageManager.RefreshInstalledPackages();
                }
                else
                {
                    installed.m_installState = installed.CompareVersionAgainst(manifest);
                }
            }
        }
Beispiel #2
0
        private static bool CheckFork(string hostUsername, PackageManifest manifest, string definedAuthor = null)
        {
            if (string.IsNullOrEmpty(hostUsername))
            {
                return(false);
            }

            definedAuthor = definedAuthor ?? manifest.author;

            return(string.Equals(hostUsername, definedAuthor, StringComparison.OrdinalIgnoreCase));
        }
Beispiel #3
0
        /// <summary>
        /// Check a package for its dependencies before enabling it.
        /// </summary>
        /// <param name="missing">If there are dependencies which are not installed at all, they will be added to this list.</param>
        /// <returns><see langword="true"/> if successful, otherwise <see langword="false"/></returns>
        internal static bool PreEnableDependencyCheck(PackageManifest package, List <string> missing)
        {
            if (!package.TryEnableAllDependencies(false))
            {
                missing.RemoveAll(it => s_enabledPackages.ContainsKey(it));

                if (missing.Any())
                {
                    string miss = "";
                    foreach (var entry in missing)
                    {
                        miss += $"\n{entry}";
                    }

                    var result = MessageBox.Show($"To enable '{package.name}', the following dependencies need to be installed:" +
                                                 $"\n" +
                                                 $"{miss}" +
                                                 $"\n\n" +
                                                 $"Do you want to install them?",
                                                 "Missing dependencies",
                                                 MessageBoxButtons.OKCancel);

                    if (result == DialogResult.Cancel)
                    {
                        return(false);
                    }
                    else
                    {
                        var check = package.TryEnableAllDependencies(true);

                        if (check == false)
                        {
                            Console.WriteLine("Check returned false!");
                            MessageBox.Show("Unable to install all dependencies!");
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
Beispiel #4
0
        /// <summary>
        /// Deserialize a package from a given JSON string (eg, the result of <see cref="JsonObject.ToString"/>).
        /// </summary>
        /// <param name="jsonString">A valid JSON string to deserialize.</param>
        /// <returns>A deserialized package if successful, otherwise <see langword="null"/>.</returns>
        internal static PackageManifest FromManifestJson(string jsonString)
        {
            try
            {
                var json = JsonReader.Parse(jsonString);

                var ret = new PackageManifest
                {
                    author            = json[nameof(author)].AsString,
                    repository        = json[nameof(repository)].AsString,
                    name              = json[nameof(name)].AsString,
                    version           = json[nameof(version)].AsString,
                    required_version  = json[nameof(required_version)].AsString,
                    description       = json[nameof(description)].AsString,
                    download_filename = json[nameof(download_filename)].AsString,
                    require_sync      = json[nameof(require_sync)].AsBoolean,
                };

                if (json[nameof(tags)].AsJsonArray is JsonArray tag)
                {
                    ret.tags = tag.Select(it => it.AsString)?.ToArray();
                }

                if (json[nameof(dependencies)].AsJsonArray is JsonArray deps)
                {
                    ret.dependencies = deps.Select(it => it.AsString)?.ToArray();
                }

                if (json[nameof(conflicts_with)].AsJsonArray is JsonArray conflicts)
                {
                    ret.conflicts_with = conflicts.Select(it => it.AsString)?.ToArray();
                }

                return(ret);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception parsing PackageManifest from Json!");
                Console.WriteLine(ex);
                //Console.WriteLine("Json string: " + jsonString);
                return(default);
Beispiel #5
0
        /// <summary>
        /// Check a package for enabled dependant packages before removing/disabling it.
        /// </summary>
        /// <param name="package"></param>
        /// <param name="disabling">Is the package just being disabled? (Just used for the dialog prompt)</param>
        /// <returns><see langword="true"/> if successful or no dependants, otherwise <see langword="false"/></returns>
        internal static bool PreRemovalDependencyCheck(PackageManifest package, bool disabling)
        {
            var dependencies = package.GetCurrentlyEnabledDependantPackages();

            bool ret = true;

            if (dependencies.Any())
            {
                string msg = "";
                foreach (var dep in dependencies)
                {
                    msg += $"\n{dep}";
                }

                string action = disabling ? "disable" : "remove";

                var msgResult = MessageBox.Show($"The following packages depend on {package.name}:" +
                                                $"\n{msg}" +
                                                $"\n\nThese will be disabled. Really {action} it?",
                                                "Dependency conflict!",
                                                MessageBoxButtons.OKCancel);

                if (msgResult != DialogResult.OK)
                {
                    ret = false;
                }
                else
                {
                    foreach (var guid in dependencies)
                    {
                        TryDisablePackage(guid, true);
                    }
                }
            }

            return(ret);
        }
Beispiel #6
0
        /// <summary>
        /// Check a package for conflicts before enabling it.
        /// </summary>
        /// <returns><see langword="true"/> if successful or no conflicts, otherwise <see langword="false"/></returns>
        internal static bool PreEnableConflictCheck(PackageManifest package)
        {
            // Check for packages which declare a conflict with this package.

            HashSet <string> conflicts = new HashSet <string>();

            if (package.HasAnyEnabledConflicts(out List <string> normConflicts))
            {
                foreach (var c in normConflicts)
                {
                    if (!conflicts.Contains(c))
                    {
                        conflicts.Add(c);
                    }
                }
            }

            var altConflicts = package.GetEnabledConflictsAlternate();

            if (altConflicts.Any())
            {
                foreach (var c in altConflicts)
                {
                    if (!conflicts.Contains(c))
                    {
                        conflicts.Add(c);
                    }
                }
            }

            if (!conflicts.Any())
            {
                return(true);
            }

            var conflictTxt = "";

            foreach (var conflict in conflicts)
            {
                conflictTxt += $"\n{conflict}";
            }

            var msgBox = MessageBox.Show($"The following packages conflict with {package.name} and need to be disabled:\n" +
                                         $"{conflictTxt}\n\n" +
                                         $"Disable them and continue?",
                                         "Conflicts detected",
                                         MessageBoxButtons.OKCancel);

            if (msgBox == DialogResult.OK)
            {
                foreach (var pkg in conflicts)
                {
                    if (!TryDisablePackage(pkg, true))
                    {
                        return(false);
                    }
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Actually download and install the provided PackageManifest instance, which would presumably be a web manifest.
        /// </summary>
        /// <param name="manifest">The PackageManifest to install.</param>
        /// <returns><see langword="true"/> if successful, otherwise <see langword="false"/></returns>
        internal static bool DownloadAndInstallPackage(PackageManifest manifest)
        {
            try
            {
                MefinoGUI.SetProgressBarActive(true);

                MefinoGUI.DisableSensitiveControls();

                var dirPath = $@"{Folders.MEFINO_DISABLED_FOLDER}\{manifest.GUID}";

                if (Directory.Exists(dirPath))
                {
                    Directory.Delete(dirPath, true);
                }

                var tempFile = TemporaryFile.CreateFile();

                var zipUrl = $"{manifest.GithubURL}/releases/latest/download/{manifest.DownloadFileName}";

                Web.WebClientManager.DownloadFileAsync(zipUrl, tempFile);

                while (Web.WebClientManager.IsBusy)
                {
                    Thread.Sleep(20);
                    MefinoApp.SendAsyncProgress(Web.WebClientManager.LastDownloadProgress);
                }

                MefinoGUI.SetProgressMessage($"Installing '{manifest.GUID}' (version {manifest.version})");

                if (ZipHelper.ExtractZip(tempFile, dirPath))
                {
                    var manifestPath = $@"{dirPath}\mefino-manifest.json";

                    if (File.Exists(manifestPath))
                    {
                        File.Delete(manifestPath);
                    }

                    File.WriteAllText(manifestPath, manifest.ToJsonObject().ToString(true));

                    //Console.WriteLine($"Installed package: {manifest.GUID} {manifest.version}");

                    MefinoGUI.SetProgressBarActive(false);

                    MefinoGUI.ReEnableSensitiveControls();

                    return(true);
                }
                else
                {
                    throw new Exception("Zip extraction failed!");
                }
            }
            catch (Exception ex)
            {
                MefinoGUI.SetProgressBarActive(false);
                MefinoGUI.ReEnableSensitiveControls();

                Console.WriteLine("Exception isntalling package '" + manifest.GUID + "'");
                Console.WriteLine($"{ex.GetType()}: {ex.Message}");
                //Mefino.SendAsyncCompletion(false);
                return(false);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Load the cached web manifests from disk.
        /// </summary>
        internal static void LoadWebManifestCache()
        {
            s_webManifests.Clear();

            if (!File.Exists(MANIFEST_CACHE_FILEPATH))
            {
                return;
            }

            try
            {
                JsonValue manifests = JsonReader.ParseFile(MANIFEST_CACHE_FILEPATH);

                var input = manifests.AsJsonObject;

                var times = input["cachetimes"].AsJsonObject;

                if (times != null)
                {
                    s_repoCacheTimes.Clear();

                    foreach (var entry in times)
                    {
                        var time = entry.Value.AsDateTime;

                        if (time == null)
                        {
                            continue;
                        }

                        if (s_repoCacheTimes.ContainsKey(entry.Key))
                        {
                            continue;
                        }

                        s_repoCacheTimes.Add(entry.Key, (DateTime)time);
                    }
                }

                var items = input["manifests"].AsJsonArray;

                foreach (var entry in items)
                {
                    var manifest = PackageManifest.FromManifestJson(entry.AsJsonObject.ToString());

                    if (manifest == default)
                    {
                        continue;
                    }

                    if (s_webManifests.ContainsKey(manifest.GUID))
                    {
                        Console.WriteLine("Duplicate manifest in web cache! Skipping: " + manifest.GUID);
                        continue;
                    }

                    manifest.m_installState = InstallState.NotInstalled;
                    s_webManifests.Add(manifest.GUID, manifest);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception parsing manifest file cache!");
                Console.WriteLine(ex);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Process a `mefino-manifest.json` file, which may be a list of manifests or just one.
        /// </summary>
        internal static void ProcessManifestFile(string manifestString, string hostUsername, string repoName, bool isFork)
        {
            var jsonVal = JsonReader.Parse(manifestString);

            if (jsonVal == default)
            {
                return;
            }

            var json = jsonVal.AsJsonObject;

            if (json == null)
            {
                return;
            }

            // Console.WriteLine("processing json " + manifestString);

            var array = json["packages"];

            if (array != JsonValue.Null && array.AsJsonArray is JsonArray packages)
            {
                string definedAuthor;
                var    name = json["author"];
                if (name != JsonValue.Null && name.AsString is string)
                {
                    definedAuthor = name.AsString;
                }
                else
                {
                    definedAuthor = null;
                }

                foreach (var entry in packages)
                {
                    var manifest = PackageManifest.FromManifestJson(entry.ToString());

                    if (isFork && !CheckFork(hostUsername, manifest, definedAuthor))
                    {
                        continue;
                    }

                    if (manifest != null)
                    {
                        ProcessManifest(manifest, hostUsername, repoName);
                    }
                }
            }
            else
            {
                var manifest = PackageManifest.FromManifestJson(manifestString);

                if (isFork && !CheckFork(hostUsername, manifest))
                {
                    return;
                }

                if (manifest != null)
                {
                    ProcessManifest(manifest, hostUsername, repoName);
                }
            }
        }