示例#1
0
        /// <summary>
        /// Load all manifest entries from a given manifest in a JAR
        /// </summary>
        /// <param name="source">source JAR</param>
        /// <param name="manifest">manifest to load</param>
        /// <returns>manifest data</returns>
        public ManifestData Load(IJar source, string path)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (path.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(path));
            }

            // If this file does not exist, obviously we cannot load it
            if (!source.Contains(path))
            {
                throw new ManifestException($"Manifest {path} does not exist");
            }

            ManifestData manifest = new ManifestData
            {
                ManifestDigest = String.Empty,
                Entries        = new List <ManifestEntry>()
            };

            // The manifest digest is supposed to refer to the digest that THIS manifest
            // expects the main manifest to have. Until set otherwise, assume this digest
            // is = to our own hash (which means loading the main manifest populates this
            // value with the main manifest hash for future comparison)
            using (Hasher h = new Hasher())
            {
                manifest.ManifestDigest = source.SHA256(h, path).ToBase64();
            }

            try
            {
                using (StreamReader reader = new StreamReader(source.Open(path)))
                {
                    string[] lines = Unwrap70(reader.ReadToEnd().Split(
                                                  new char[]
                    {
                        (char)10,
                        (char)13
                    },
                                                  StringSplitOptions.RemoveEmptyEntries));

                    Populate(manifest, lines);
                }
            }
            catch (Exception ex)
            {
                throw new ManifestException($"Failed to open or parse manifest {path}", ex);
            }

            return(manifest);
        }
示例#2
0
        /// <summary>
        /// Populate the entries in a manfiest from the given text lines
        /// </summary>
        /// <param name="manifest">manifest to populate</param>
        /// <param name="lines">individual manifest lines</param>
        private void Populate(ManifestData manifest, string[] lines)
        {
            for (int ptr = 0; ptr < lines.Length; ptr++)
            {
                string line = lines[ptr];

                // Split each line into  NAME: VALUE
                string[] parts = lines[ptr].Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);

                if (parts.Length == 2)
                {
                    // Is it a filename?
                    if (parts[0].Equals("Name", StringComparison.InvariantCultureIgnoreCase))
                    {
                        // There must be a digest so split the next line in half too
                        string[] digestParts = lines[ptr + 1].Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);

                        manifest.Entries.Add(new ManifestEntry
                        {
                            Path   = parts[1].TrimStart(),
                            Digest = digestParts[1].TrimStart(),

                            // Preserve spacing structure for SF hashing comparison
                            //
                            // The newlines are important and this is the only document that really tells you:
                            // https://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html
                            // "hash of the **three** lines in the manifest file for the source file."
                            //
                            Original =
                                Wrap70(lines[ptr]) + Environment.NewLine +
                                Wrap70(lines[ptr + 1]) + Environment.NewLine + Environment.NewLine
                        });

                        // Skip the line after us because have already read it
                        ptr++;
                        continue;
                    }

                    // Is it the manifest hash?
                    if (parts[0].EndsWith("Digest-Manifest", StringComparison.InvariantCultureIgnoreCase))
                    {
                        // Second half MUST be the hash (and MANIFEST.MF cannot wrap)
                        manifest.ManifestDigest = parts[1].TrimStart();
                    }
                }
            }
        }