private static bool IsBundlePackage(string path)
 {
     try
     {
         using IAppxFileReader fileReader = new ZipArchiveFileReaderAdapter(path);
         return(fileReader.FileExists(FileConstants.AppxBundleManifestFilePath));
     }
     catch (Exception)
     {
         return(false);
     }
 }
Пример #2
0
 private static bool IsMsixPackage(string path)
 {
     try
     {
         using (IAppxFileReader fileReader = new ZipArchiveFileReaderAdapter(path))
         {
             return(fileReader.FileExists("AppxBlockMap.xml"));
         }
     }
     catch (Exception)
     {
         return(false);
     }
 }
Пример #3
0
 private static bool IsBundlePackage(string path)
 {
     try
     {
         using (IAppxFileReader fileReader = new ZipArchiveFileReaderAdapter(path))
         {
             return(fileReader.FileExists("AppxMetadata\\AppxBundleManifest.xml"));
         }
     }
     catch (Exception)
     {
         return(false);
     }
 }
Пример #4
0
        public async Task <string> CalculateSignatureHashAsync(FileInfo fileInfo, CancellationToken cancellationToken = default, IProgress <ProgressData> progress = null)
        {
            var ext = Path.GetExtension(fileInfo.FullName);

            if (
                string.Equals(".appx", ext, StringComparison.OrdinalIgnoreCase) ||
                string.Equals(".msix", ext, StringComparison.OrdinalIgnoreCase) ||
                string.Equals(".appxbundle", ext, StringComparison.OrdinalIgnoreCase) ||
                string.Equals(".msixbundle", ext, StringComparison.OrdinalIgnoreCase))
            {
                using (IAppxFileReader src = new ZipArchiveFileReaderAdapter(fileInfo.FullName))
                {
                    if (src.FileExists("AppxSignature.p7x"))
                    {
                        using (var appxSignature = src.GetFile("AppxSignature.p7x"))
                        {
                            var buffer = new byte[ushort.MaxValue];
                            var read   = await appxSignature.ReadAsync(buffer, 0, ushort.MaxValue, cancellationToken).ConfigureAwait(false);

                            var builder = new StringBuilder();

                            using (var sha = SHA256.Create())
                            {
                                foreach (var b in sha.ComputeHash(buffer, 0, read))
                                {
                                    cancellationToken.ThrowIfCancellationRequested();
                                    builder.Append(b.ToString("X2"));
                                }

                                return(builder.ToString());
                            }
                        }
                    }

                    throw new ArgumentException($"The file '{fileInfo.Name}' does not contain a signature.", nameof(fileInfo));
                }
            }

            var directory = fileInfo.Directory;
            // ReSharper disable once PossibleNullReferenceException
            var signatureInfo = new FileInfo(Path.Combine(directory.FullName, "AppxSignature.p7x"));

            if (signatureInfo.Exists)
            {
                return(await CalculateHashAsync(signatureInfo, cancellationToken, progress).ConfigureAwait(false));
            }

            throw new ArgumentException("Only MSIX/APPX formats support signature footprints.", nameof(fileInfo));
        }
Пример #5
0
        public async Task <AppxIdentity> GetIdentity(Stream file, CancellationToken cancellationToken = default)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            Logger.Info("Reading identity from stream of type " + file.GetType().Name);

            if (file is FileStream fileStream)
            {
                Logger.Debug("The input is a file stream, trying to evaluate its name...");
                switch (Path.GetExtension(fileStream.Name).ToLowerInvariant())
                {
                case FileConstants.AppxBundleExtension:
                case FileConstants.MsixBundleExtension:
                {
                    Logger.Info("The file seems to be a bundle package (compressed).");
                    try
                    {
                        using IAppxFileReader reader = new ZipArchiveFileReaderAdapter(fileStream);
                        return(await GetIdentityFromBundleManifest(reader.GetFile(FileConstants.AppxBundleManifestFilePath), cancellationToken).ConfigureAwait(false));
                    }
                    catch (FileNotFoundException e)
                    {
                        throw new ArgumentException("File  " + fileStream.Name + " is not an APPX/MSIX bundle, because it does not contain a manifest.", nameof(file), e);
                    }
                }

                case FileConstants.AppxExtension:
                case FileConstants.MsixExtension:
                {
                    Logger.Info("The file seems to be a package (compressed).");
                    try
                    {
                        using IAppxFileReader reader = new ZipArchiveFileReaderAdapter(fileStream);
                        return(await GetIdentityFromBundleManifest(reader.GetFile(FileConstants.AppxManifestFile), cancellationToken).ConfigureAwait(false));
                    }
                    catch (FileNotFoundException e)
                    {
                        throw new ArgumentException("File " + fileStream.Name + " is not an APPX/MSIX package, because it does not contain a manifest.", nameof(file), e);
                    }
                }
                }

                switch (Path.GetFileName(fileStream.Name).ToLowerInvariant())
                {
                case FileConstants.AppxManifestFile:
                    Logger.Info("The file seems to be a package (manifest).");
                    return(await GetIdentityFromPackageManifest(fileStream, cancellationToken).ConfigureAwait(false));

                case FileConstants.AppxBundleManifestFile:
                    Logger.Info("The file seems to be a bundle (manifest).");
                    return(await GetIdentityFromBundleManifest(fileStream, cancellationToken).ConfigureAwait(false));
                }
            }

            try
            {
                Logger.Debug("Trying to interpret the input file as an XML manifest...");
                var doc = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken).ConfigureAwait(false);

                var firstElement = doc.Elements().FirstOrDefault();
                if (firstElement != null)
                {
                    if (firstElement.Name.LocalName == "Package")
                    {
                        Logger.Info("The file seems to be a package (manifest).");
                        return(GetIdentityFromPackageManifest(doc));
                    }

                    if (firstElement.Name.LocalName == "Bundle")
                    {
                        Logger.Info("The file seems to be a bundle (manifest).");
                        return(GetIdentityFromBundleManifest(doc));
                    }

                    // This is an XML file but neither a package manifest or a bundle manifest, so we can stop here.
                    throw new ArgumentException("This XML file is neither package nor a bundle manifest (missing <Package /> or <Bundle /> root element).");
                }
            }
            catch
            {
                // this is ok, it seems that the file was not XML so we should continue to find out some other possibilities
                Logger.Debug("The file was not in XML format (exception thrown during parsing).");
            }

            try
            {
                file.Seek(0, SeekOrigin.Begin);
                using var zip = new ZipArchive(file, ZipArchiveMode.Read, true);
                using IAppxFileReader reader = new ZipArchiveFileReaderAdapter(zip);

                if (reader.FileExists(FileConstants.AppxManifestFile))
                {
                    return(await GetIdentityFromPackageManifest(reader.GetFile(FileConstants.AppxManifestFile), cancellationToken).ConfigureAwait(false));
                }

                if (reader.FileExists(FileConstants.AppxBundleManifestFilePath))
                {
                    return(await GetIdentityFromBundleManifest(reader.GetFile(FileConstants.AppxBundleManifestFilePath), cancellationToken).ConfigureAwait(false));
                }

                // This is a ZIP archive but neither a package or bundle, so we can stop here.
                throw new ArgumentException("This compressed file is neither an APPX/MSIX or bundle because it contains no manifest file.");
            }
            catch
            {
                // this is ok, it seems that the file was not ZIP format so we should continue to find out some other possibilities
                Logger.Debug("The file was not in ZIP format (exception thrown during opening).");
            }

            throw new ArgumentException("The input stream is neither a valid manifest or package file.");
        }