예제 #1
0
        /// <summary>
        /// Given a stanza and an open zipfile, returns all files that would be installed
        /// for this stanza.
        ///
        /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
        ///
        /// Throws a BadInstallLocationKraken if the install stanza targets an
        /// unknown install location (eg: not GameData, Ships, etc)
        ///
        /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
        /// </summary>
        internal static List <InstallableFile> FindInstallableFiles(ModuleInstallDescriptor stanza, ZipFile zipfile, KSP ksp)
        {
            string installDir;
            bool   makeDirs;
            var    files = new List <InstallableFile> ();

            if (stanza.install_to == "GameData")
            {
                installDir = ksp == null ? null : ksp.GameData();
                makeDirs   = true;
            }
            else if (stanza.install_to == "Ships")
            {
                installDir = ksp == null ? null : ksp.Ships();
                makeDirs   = false; // Don't allow directory creation in ships directory
            }
            else if (stanza.install_to == "Tutorial")
            {
                installDir = ksp == null ? null : ksp.Tutorial();
                makeDirs   = true;
            }
            else if (stanza.install_to == "GameRoot")
            {
                installDir = ksp == null ? null : ksp.GameDir();
                makeDirs   = false;
            }
            else
            {
                throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to);
            }

            // O(N^2) solution, as we're walking the zipfile for each stanza.
            // Surely there's a better way, although this is fast enough we may not care.

            foreach (ZipEntry entry in zipfile)
            {
                // Skips things not prescribed by our install stanza.
                if (!stanza.IsWanted(entry.Name))
                {
                    continue;
                }

                // Prepare our file info.
                InstallableFile file_info = new InstallableFile();
                file_info.source      = entry;
                file_info.makedir     = makeDirs;
                file_info.destination = null;

                // If we have a place to install it, fill that in...
                if (installDir != null)
                {
                    // Get the full name of the file.
                    string outputName = entry.Name;

                    // Update our file info with the install location
                    file_info.destination = TransformOutputName(stanza.file, outputName, installDir);
                }

                files.Add(file_info);
            }

            // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93)
            if (files.Count == 0)
            {
                // We have null as the first argument here, because we don't know which module we're installing
                throw new BadMetadataKraken(null, String.Format("No files found in {0} to install!", stanza.file));
            }

            return(files);
        }
예제 #2
0
        /// <summary>
        /// Given a stanza and an open zipfile, returns all files that would be installed
        /// for this stanza.
        ///
        /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
        ///
        /// Throws a BadInstallLocationKraken if the install stanza targets an
        /// unknown install location (eg: not GameData, Ships, etc)
        ///
        /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
        /// </summary>
        /// <exception cref="BadInstallLocationKraken">Thrown when the installation path is not valid according to the spec.</exception>
        internal static List <InstallableFile> FindInstallableFiles(ModuleInstallDescriptor stanza, ZipFile zipfile, KSP ksp)
        {
            string installDir;
            bool   makeDirs;
            var    files = new List <InstallableFile> ();

            // Normalize the path before doing everything else
            // TODO: This really should happen in the ModuleInstallDescriptor itself.
            stanza.install_to = KSPPathUtils.NormalizePath(stanza.install_to);

            // Convert our stanza to a standard `file` type. This is a no-op if it's
            // already the basic type.

            stanza = stanza.ConvertFindToFile(zipfile);

            if (stanza.install_to == "GameData" || stanza.install_to.StartsWith("GameData/"))
            {
                // The installation path can be either "GameData" or a sub-directory of "GameData"
                // but it cannot contain updirs
                if (stanza.install_to.Contains("/../") || stanza.install_to.EndsWith("/.."))
                {
                    throw new BadInstallLocationKraken("Invalid installation path: " + stanza.install_to);
                }

                string subDir = stanza.install_to.Substring("GameData".Length);    // remove "GameData"
                subDir = subDir.StartsWith("/") ? subDir.Substring(1) : subDir;    // remove a "/" at the beginning, if present

                // Add the extracted subdirectory to the path of KSP's GameData
                installDir = ksp == null ? null : (KSPPathUtils.NormalizePath(ksp.GameData() + "/" + subDir));
                makeDirs   = true;
            }
            else if (stanza.install_to.StartsWith("Ships"))
            {
                // Don't allow directory creation in ships directory
                makeDirs = false;

                switch (stanza.install_to)
                {
                case "Ships":
                    installDir = ksp == null ? null : ksp.Ships();
                    break;

                case "Ships/VAB":
                    installDir = ksp == null ? null : ksp.ShipsVab();
                    break;

                case "Ships/SPH":
                    installDir = ksp == null ? null : ksp.ShipsSph();
                    break;

                default:
                    throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to);
                }
            }
            else
            {
                switch (stanza.install_to)
                {
                case "Tutorial":
                    installDir = ksp == null ? null : ksp.Tutorial();
                    makeDirs   = true;
                    break;

                case "Scenarios":
                    installDir = ksp == null ? null : ksp.Scenarios();
                    makeDirs   = true;
                    break;

                case "GameRoot":
                    installDir = ksp == null ? null : ksp.GameDir();
                    makeDirs   = false;
                    break;

                default:
                    throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to);
                }
            }

            // O(N^2) solution, as we're walking the zipfile for each stanza.
            // Surely there's a better way, although this is fast enough we may not care.

            foreach (ZipEntry entry in zipfile)
            {
                // Skips things not prescribed by our install stanza.
                if (!stanza.IsWanted(entry.Name))
                {
                    continue;
                }

                // Prepare our file info.
                InstallableFile file_info = new InstallableFile
                {
                    source      = entry,
                    makedir     = makeDirs,
                    destination = null
                };

                // If we have a place to install it, fill that in...
                if (installDir != null)
                {
                    // Get the full name of the file.
                    string outputName = entry.Name;

                    // Update our file info with the install location
                    file_info.destination = TransformOutputName(stanza.file, outputName, installDir);
                }

                files.Add(file_info);
            }

            // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93)
            if (files.Count == 0)
            {
                // We have null as the first argument here, because we don't know which module we're installing
                throw new BadMetadataKraken(null, String.Format("No files found in {0} to install!", stanza.file));
            }

            return(files);
        }
예제 #3
0
        /// <summary>
        /// Given a stanza and an open zipfile, returns all files that would be installed
        /// for this stanza.
        ///
        /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
        ///
        /// Throws a BadInstallLocationKraken if the install stanza targets an
        /// unknown install location (eg: not GameData, Ships, etc)
        ///
        /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
        /// </summary>
        /// <exception cref="BadInstallLocationKraken">Thrown when the installation path is not valid according to the spec.</exception>
        internal static List<InstallableFile> FindInstallableFiles(ModuleInstallDescriptor stanza, ZipFile zipfile, KSP ksp)
        {
            string installDir;
            bool makeDirs;
            var files = new List<InstallableFile> ();

            // Normalize the path before doing everything else
            // TODO: This really should happen in the ModuleInstallDescriptor itself.
            stanza.install_to = KSPPathUtils.NormalizePath(stanza.install_to);

            // Convert our stanza to a standard `file` type. This is a no-op if it's
            // already the basic type.

            stanza = stanza.ConvertFindToFile(zipfile);

            if (stanza.install_to == "GameData" || stanza.install_to.StartsWith("GameData/"))
            {
                // The installation path can be either "GameData" or a sub-directory of "GameData"
                // but it cannot contain updirs
                if (stanza.install_to.Contains("/../") || stanza.install_to.EndsWith("/.."))
                    throw new BadInstallLocationKraken("Invalid installation path: " + stanza.install_to);

                string subDir = stanza.install_to.Substring("GameData".Length);    // remove "GameData"
                subDir = subDir.StartsWith("/") ? subDir.Substring(1) : subDir;    // remove a "/" at the beginning, if present

                // Add the extracted subdirectory to the path of KSP's GameData
                installDir = ksp == null ? null : (KSPPathUtils.NormalizePath(ksp.GameData() + "/" + subDir));
                makeDirs = true;
            }
            else if (stanza.install_to.StartsWith("Ships"))
            {
                // Don't allow directory creation in ships directory
                makeDirs = false;

                switch (stanza.install_to)
                {
                    case "Ships":
                        installDir = ksp == null ? null : ksp.Ships();
                        break;
                    case "Ships/VAB":
                        installDir = ksp == null ? null : ksp.ShipsVab();
                        break;
                    case "Ships/SPH":
                        installDir = ksp == null ? null : ksp.ShipsSph();
                        break;
                    case "Ships/@thumbs":
                        installDir = ksp == null ? null : ksp.ShipsThumbs();
                        break;
                    case "Ships/@thumbs/VAB":
                        installDir = ksp == null ? null : ksp.ShipsThumbsVAB();
                        break;
                    case "Ships/@thumbs/SPH":
                        installDir = ksp == null ? null : ksp.ShipsThumbsSPH();
                        break;
                    default:
                        throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to);
                }
            }
            else switch (stanza.install_to)
            {
                case "Tutorial":
                    installDir = ksp == null ? null : ksp.Tutorial();
                    makeDirs = true;
                    break;

                case "Scenarios":
                    installDir = ksp == null ? null : ksp.Scenarios();
                    makeDirs = true;
                    break;

                case "GameRoot":
                    installDir = ksp == null ? null : ksp.GameDir();
                    makeDirs = false;
                    break;

                default:
                    throw new BadInstallLocationKraken("Unknown install_to " + stanza.install_to);
            }

            // O(N^2) solution, as we're walking the zipfile for each stanza.
            // Surely there's a better way, although this is fast enough we may not care.

            foreach (ZipEntry entry in zipfile)
            {
                // Skips things not prescribed by our install stanza.
                if (! stanza.IsWanted(entry.Name)) {
                    continue;
                }

                // Prepare our file info.
                InstallableFile file_info = new InstallableFile
                {
                    source = entry,
                    makedir = makeDirs,
                    destination = null
                };

                // If we have a place to install it, fill that in...
                if (installDir != null)
                {
                    // Get the full name of the file.
                    string outputName = entry.Name;

                    // Update our file info with the install location
                    file_info.destination = TransformOutputName(stanza.file, outputName, installDir);
                }

                files.Add(file_info);
            }

            // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93)
            if (files.Count == 0)
            {
                // We have null as the first argument here, because we don't know which module we're installing
                throw new BadMetadataKraken(null, String.Format("No files found in {0} to install!", stanza.file));
            }

            return files;
        }
예제 #4
0
        /// <summary>
        /// Given an open zipfile, returns all files that would be installed
        /// for this stanza.
        ///
        /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
        ///
        /// Throws a BadInstallLocationKraken if the install stanza targets an
        /// unknown install location (eg: not GameData, Ships, etc)
        ///
        /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
        /// </summary>
        /// <exception cref="BadInstallLocationKraken">Thrown when the installation path is not valid according to the spec.</exception>
        public List <InstallableFile> FindInstallableFiles(ZipFile zipfile, GameInstance ksp)
        {
            string installDir;
            var    files = new List <InstallableFile>();

            // Normalize the path before doing everything else
            string install_to = CKANPathUtils.NormalizePath(this.install_to);

            // The installation path cannot contain updirs
            if (install_to.Contains("/../") || install_to.EndsWith("/.."))
            {
                throw new BadInstallLocationKraken("Invalid installation path: " + install_to);
            }

            if (ksp == null)
            {
                installDir = null;
            }
            else if (install_to == ksp.game.PrimaryModDirectoryRelative ||
                     install_to.StartsWith($"{ksp.game.PrimaryModDirectoryRelative}/"))
            {
                // The installation path can be either "GameData" or a sub-directory of "GameData"
                string subDir = install_to.Substring(ksp.game.PrimaryModDirectoryRelative.Length); // remove "GameData"
                subDir = subDir.StartsWith("/") ? subDir.Substring(1) : subDir;                    // remove a "/" at the beginning, if present

                // Add the extracted subdirectory to the path of KSP's GameData
                installDir = CKANPathUtils.NormalizePath(ksp.game.PrimaryModDirectory(ksp) + "/" + subDir);
            }
            else
            {
                switch (install_to)
                {
                case "GameRoot":
                    installDir = ksp.GameDir();
                    break;

                default:
                    if (ksp.game.AllowInstallationIn(install_to, out string path))
                    {
                        installDir = ksp.ToAbsoluteGameDir(path);
                    }
                    else
                    {
                        throw new BadInstallLocationKraken("Unknown install_to " + install_to);
                    }
                    break;
                }
            }

            EnsurePattern();

            // `find` is supposed to match the "topmost" folder. Find it.
            var shortestMatch = find == null ? (int?)null
                : zipfile.Cast <ZipEntry>()
                                .Select(entry => inst_pattern.Match(entry.Name.Replace('\\', '/')))
                                .Where(match => match.Success)
                                .DefaultIfEmpty()
                                .Min(match => match?.Index);

            // O(N^2) solution, as we're walking the zipfile for each stanza.
            // Surely there's a better way, although this is fast enough we may not care.
            foreach (ZipEntry entry in zipfile)
            {
                // Skips dirs and things not prescribed by our install stanza.
                if (!IsWanted(entry.Name, shortestMatch))
                {
                    continue;
                }

                // Prepare our file info.
                InstallableFile file_info = new InstallableFile
                {
                    source      = entry,
                    makedir     = false,
                    destination = null
                };

                // If we have a place to install it, fill that in...
                if (installDir != null)
                {
                    // Get the full name of the file.
                    // Update our file info with the install location
                    file_info.destination = TransformOutputName(
                        ksp.game, entry.Name, installDir, @as);
                    file_info.makedir = AllowDirectoryCreation(
                        ksp.game,
                        ksp?.ToRelativeGameDir(file_info.destination)
                        ?? file_info.destination);
                }

                files.Add(file_info);
            }

            // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93)
            if (files.Count == 0)
            {
                // We have null as the first argument here, because we don't know which module we're installing
                throw new BadMetadataKraken(null, String.Format("No files found matching {0} to install!", DescribeMatch()));
            }

            return(files);
        }
예제 #5
0
        /// <summary>
        /// Given an open zipfile, returns all files that would be installed
        /// for this stanza.
        ///
        /// If a KSP instance is provided, it will be used to generate output paths, otherwise these will be null.
        ///
        /// Throws a BadInstallLocationKraken if the install stanza targets an
        /// unknown install location (eg: not GameData, Ships, etc)
        ///
        /// Throws a BadMetadataKraken if the stanza resulted in no files being returned.
        /// </summary>
        /// <exception cref="BadInstallLocationKraken">Thrown when the installation path is not valid according to the spec.</exception>
        public List <InstallableFile> FindInstallableFiles(ZipFile zipfile, KSP ksp)
        {
            string installDir;
            bool   makeDirs;
            var    files = new List <InstallableFile>();

            // Normalize the path before doing everything else
            string install_to = KSPPathUtils.NormalizePath(this.install_to);

            if (install_to == "GameData" || install_to.StartsWith("GameData/"))
            {
                // The installation path can be either "GameData" or a sub-directory of "GameData"
                // but it cannot contain updirs
                if (install_to.Contains("/../") || install_to.EndsWith("/.."))
                {
                    throw new BadInstallLocationKraken("Invalid installation path: " + install_to);
                }

                string subDir = install_to.Substring("GameData".Length);        // remove "GameData"
                subDir = subDir.StartsWith("/") ? subDir.Substring(1) : subDir; // remove a "/" at the beginning, if present

                // Add the extracted subdirectory to the path of KSP's GameData
                installDir = ksp == null ? null : (KSPPathUtils.NormalizePath(ksp.GameData() + "/" + subDir));
                makeDirs   = true;
            }
            else if (install_to.StartsWith("Ships"))
            {
                // Don't allow directory creation in ships directory
                makeDirs = false;

                switch (install_to)
                {
                case "Ships":
                    installDir = ksp?.Ships();
                    break;

                case "Ships/VAB":
                    installDir = ksp?.ShipsVab();
                    break;

                case "Ships/SPH":
                    installDir = ksp?.ShipsSph();
                    break;

                case "Ships/@thumbs":
                    installDir = ksp?.ShipsThumbs();
                    break;

                case "Ships/@thumbs/VAB":
                    installDir = ksp?.ShipsThumbsVAB();
                    break;

                case "Ships/@thumbs/SPH":
                    installDir = ksp?.ShipsThumbsSPH();
                    break;

                default:
                    throw new BadInstallLocationKraken("Unknown install_to " + install_to);
                }
            }
            else
            {
                switch (install_to)
                {
                case "Tutorial":
                    installDir = ksp?.Tutorial();
                    makeDirs   = true;
                    break;

                case "Scenarios":
                    installDir = ksp?.Scenarios();
                    makeDirs   = true;
                    break;

                case "Missions":
                    installDir = ksp?.Missions();
                    makeDirs   = true;
                    break;

                case "GameRoot":
                    installDir = ksp?.GameDir();
                    makeDirs   = false;
                    break;

                default:
                    throw new BadInstallLocationKraken("Unknown install_to " + install_to);
                }
            }

            EnsurePattern();

            // `find` is supposed to match the "topmost" folder. Find it.
            var shortestMatch = find == null ? (int?)null
                : zipfile.Cast <ZipEntry>()
                                .Select(entry => inst_pattern.Match(entry.Name.Replace('\\', '/')))
                                .Where(match => match.Success)
                                .Min(match => match.Index);

            // O(N^2) solution, as we're walking the zipfile for each stanza.
            // Surely there's a better way, although this is fast enough we may not care.
            foreach (ZipEntry entry in zipfile)
            {
                // Skips dirs and things not prescribed by our install stanza.
                if (!IsWanted(entry.Name, shortestMatch))
                {
                    continue;
                }

                // Prepare our file info.
                InstallableFile file_info = new InstallableFile
                {
                    source      = entry,
                    makedir     = makeDirs,
                    destination = null
                };

                // If we have a place to install it, fill that in...
                if (installDir != null)
                {
                    // Get the full name of the file.
                    // Update our file info with the install location
                    file_info.destination = TransformOutputName(
                        entry.Name, installDir, @as);
                }

                files.Add(file_info);
            }

            // If we have no files, then something is wrong! (KSP-CKAN/CKAN#93)
            if (files.Count == 0)
            {
                // We have null as the first argument here, because we don't know which module we're installing
                throw new BadMetadataKraken(null, String.Format("No files found matching {0} to install!", DescribeMatch()));
            }

            return(files);
        }