/// <summary> /// Retrieves the specified component from NuGet. /// </summary> /// <param name="name">NuGet package name</param> /// <param name="version">Package version</param> /// <returns></returns> public async Task <Component> GetComponentAsync(string name, string version) { if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(version)) { return(null); } Console.WriteLine("Retrieving " + name + " " + version); var component = new Component { Name = name, Version = version, Purl = Utils.GeneratePackageUrl(name, version) }; var url = _baseUrl + name + "/" + version + "/" + name + ".nuspec"; var doc = await _httpClient.GetXmlAsync(url); if (doc == null) { return(component); } var root = doc.DocumentElement; var metadata = root.SelectSingleNode("/*[local-name() = 'package']/*[local-name() = 'metadata']"); component.Publisher = GetNodeValue(metadata, "/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'authors']"); component.Copyright = GetNodeValue(metadata, "/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'copyright']"); var title = GetNodeValue(metadata, "/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'title']"); var summary = GetNodeValue(metadata, "/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'summary']"); var description = GetNodeValue(metadata, "/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'description']"); if (summary != null) { component.Description = summary; } else if (description != null) { component.Description = description; } else if (title != null) { component.Description = title; } // Utilize the new license expression field present in more recent packages // TODO: Need to have more robust parsing to support composite expressions seen in (https://github.com/NuGet/Home/wiki/Packaging-License-within-the-nupkg#project-properties) var licenseNode = metadata.SelectSingleNode("/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'license']"); var licenseUrlNode = metadata.SelectSingleNode("/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'licenseUrl']"); if (licenseNode?.Attributes["type"].Value == "expression") { var licenses = licenseNode.FirstChild.Value .Replace("AND", ";") .Replace("OR", ";") .Replace("WITH", ";") .Replace("+", "") .Split(';').ToList(); foreach (var license in licenses) { component.Licenses.Add(new Models.License { Id = license.Trim(), Name = license.Trim() }); } } else if (licenseUrlNode != null) { var licenseUrl = licenseUrlNode.FirstChild.Value; var license = await _githubService.GetLicenseAsync(licenseUrl.Trim()); component.Licenses.Add(license ?? new Models.License { Url = licenseUrl.Trim() }); } var projectUrl = GetNodeValue(metadata, "/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'projectUrl']"); if (projectUrl != null) { var externalReference = new Models.ExternalReference(); externalReference.Type = Models.ExternalReference.WEBSITE; externalReference.Url = projectUrl; component.ExternalReferences.Add(externalReference); } var dependencies = metadata.SelectNodes("/*[local-name() = 'package']/*[local-name() = 'metadata']/*[local-name() = 'dependencies']/*[local-name() = 'dependency']"); foreach (XmlNode dependency in dependencies) { var dependencyName = dependency.Attributes["id"]; var dependencyVersion = dependency.Attributes["version"]; if (dependencyName != null && dependencyVersion != null) { var nugetDependency = new NugetPackage { Name = dependencyName.Value, Version = dependencyVersion.Value, }; component.Dependencies.Add(nugetDependency); } } return(component); }
/// <summary> /// Retrieves the specified component from NuGet. /// </summary> /// <param name="name">NuGet package name</param> /// <param name="version">Package version</param> /// <returns></returns> public async Task <Component> GetComponentAsync(string name, string version, string scope) { if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(version)) { return(null); } Console.WriteLine("Retrieving " + name + " " + version); var component = new Component { Name = name, Version = version, Scope = scope, Purl = Core.Utils.GeneratePackageUrl(name, version), Type = Component.ComponentType.Library }; var nuspecFilename = GetCachedNuspecFilename(name, version); NuspecReader nuspecReader = null; if (nuspecFilename == null) { var url = _baseUrl + name + "/" + version + "/" + name + ".nuspec"; using (var xmlStream = await _httpClient.GetXmlStreamAsync(url).ConfigureAwait(false)) { if (xmlStream != null) { nuspecReader = new NuspecReader(xmlStream); } } } else { using (var xmlStream = _fileSystem.File.Open(nuspecFilename, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { nuspecReader = new NuspecReader(xmlStream); } } if (nuspecReader == null) { return(component); } component.Publisher = nuspecReader.GetAuthors(); component.Copyright = nuspecReader.GetCopyright(); // this prevents empty copyright values in the JSON BOM if (string.IsNullOrEmpty(component.Copyright)) { component.Copyright = null; } var title = nuspecReader.GetTitle(); var summary = nuspecReader.GetSummary(); var description = nuspecReader.GetDescription(); if (!string.IsNullOrEmpty(summary)) { component.Description = summary; } else if (!string.IsNullOrEmpty(description)) { component.Description = description; } else if (!string.IsNullOrEmpty(title)) { component.Description = title; } var licenseMetadata = nuspecReader.GetLicenseMetadata(); if (licenseMetadata != null && licenseMetadata.Type == NuGet.Packaging.LicenseType.Expression) { Action <NuGetLicense> licenseProcessor = delegate(NuGetLicense nugetLicense) { var license = new Models.v1_2.License { Id = nugetLicense.Identifier, Name = nugetLicense.Identifier }; component.Licenses = new List <ComponentLicense> { new ComponentLicense { License = license } }; }; licenseMetadata.LicenseExpression.OnEachLeafNode(licenseProcessor, null); } else { var licenseUrl = nuspecReader.GetLicenseUrl(); if (!string.IsNullOrEmpty(licenseUrl)) { Models.v1_2.License license = null; if (_githubService != null) { license = await _githubService.GetLicenseAsync(licenseUrl).ConfigureAwait(false); } if (license == null) { license = new Models.v1_2.License { Url = licenseUrl }; } component.Licenses = new List <ComponentLicense> { new ComponentLicense { License = license } }; } } var projectUrl = nuspecReader.GetProjectUrl(); if (!string.IsNullOrEmpty(projectUrl)) { var externalReference = new Models.v1_2.ExternalReference(); externalReference.Type = Models.v1_2.ExternalReference.ExternalReferenceType.Website; externalReference.Url = projectUrl; component.ExternalReferences = new List <ExternalReference> { externalReference }; } // Source: https://docs.microsoft.com/de-de/nuget/reference/nuspec#repository var repoMeta = nuspecReader.GetRepositoryMetadata(); var vcsUrl = repoMeta?.Url; if (!string.IsNullOrEmpty(vcsUrl)) { var externalReference = new Models.v1_2.ExternalReference(); externalReference.Type = Models.v1_2.ExternalReference.ExternalReferenceType.Vcs; externalReference.Url = vcsUrl; if (null == component.ExternalReferences) { component.ExternalReferences = new List <ExternalReference> { externalReference }; } else { component.ExternalReferences.Add(externalReference); } } return(component); }
/// <summary> /// Retrieves the specified component from NuGet. /// </summary> /// <param name="name">NuGet package name</param> /// <param name="version">Package version</param> /// <returns></returns> public async Task <Component> GetComponentAsync(string name, string version, string scope) { if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(version)) { return(null); } Console.WriteLine("Retrieving " + name + " " + version); var component = new Component { Name = name, Version = version, Scope = scope, Purl = Core.Utils.GeneratePackageUrl(name, version), Type = Component.ComponentType.Library }; var nuspecFilename = GetCachedNuspecFilename(name, version); NuspecReader nuspecReader = null; byte[] hashBytes = null; if (nuspecFilename == null) { var nugetUrlPrefix = _baseUrl + name + "/" + version + "/" + name; var nuspecUrl = nugetUrlPrefix + _nuspecExtension; var nupkgUrl = nugetUrlPrefix + "." + version + _nupkgExtension; using (var xmlStream = await _httpClient.GetStreamWithStatusCheckAsync(nuspecUrl).ConfigureAwait(false)) { if (xmlStream != null) { nuspecReader = new NuspecReader(xmlStream); } } using (var stream = await _httpClient.GetStreamWithStatusCheckAsync(nupkgUrl).ConfigureAwait(false)) { if (stream != null) { hashBytes = ComputeSha215Hash(stream); } } } else { using (var xmlStream = _fileSystem.File.OpenRead(nuspecFilename)) { nuspecReader = new NuspecReader(xmlStream); } // reference: https://docs.microsoft.com/en-us/nuget/reference/cli-reference/cli-ref-add // and: https://github.com/NuGet/Home/wiki/Nupkg-Metadata-File // └─<packageID> // └─<version> // ├─<packageID>.<version>.nupkg // ├─<packageID>.<version>.nupkg.sha512 // └─<packageID>.nuspec string shaFilename = Path.ChangeExtension(nuspecFilename, version + _sha512Extension); string nupkgFilename = Path.ChangeExtension(nuspecFilename, version + _nupkgExtension); if (_fileSystem.File.Exists(shaFilename)) { string base64Hash = _fileSystem.File.ReadAllText(shaFilename); hashBytes = Convert.FromBase64String(base64Hash); } else if (_fileSystem.File.Exists(nupkgFilename)) { using (var nupkgStream = _fileSystem.File.OpenRead(nupkgFilename)) { hashBytes = ComputeSha215Hash(nupkgStream); } } } if (hashBytes != null) { var hex = BitConverter.ToString(hashBytes).Replace("-", string.Empty); Hash h = new Hash() { Alg = Hash.HashAlgorithm.SHA_512, Content = hex }; component.Hashes = new List <Hash>() { h }; } if (nuspecReader == null) { return(component); } component.Publisher = nuspecReader.GetAuthors(); component.Copyright = nuspecReader.GetCopyright(); // this prevents empty copyright values in the JSON BOM if (string.IsNullOrEmpty(component.Copyright)) { component.Copyright = null; } var title = nuspecReader.GetTitle(); var summary = nuspecReader.GetSummary(); var description = nuspecReader.GetDescription(); if (!string.IsNullOrEmpty(summary)) { component.Description = summary; } else if (!string.IsNullOrEmpty(description)) { component.Description = description; } else if (!string.IsNullOrEmpty(title)) { component.Description = title; } var licenseMetadata = nuspecReader.GetLicenseMetadata(); if (licenseMetadata != null && licenseMetadata.Type == NuGet.Packaging.LicenseType.Expression) { Action <NuGetLicense> licenseProcessor = delegate(NuGetLicense nugetLicense) { var license = new Models.v1_2.License { Id = nugetLicense.Identifier, Name = nugetLicense.Identifier }; component.Licenses = new List <ComponentLicense> { new ComponentLicense { License = license } }; }; licenseMetadata.LicenseExpression.OnEachLeafNode(licenseProcessor, null); } else { var licenseUrl = nuspecReader.GetLicenseUrl(); if (!string.IsNullOrEmpty(licenseUrl)) { Models.v1_2.License license = null; if (_githubService != null) { license = await _githubService.GetLicenseAsync(licenseUrl).ConfigureAwait(false); } if (license == null) { license = new Models.v1_2.License { Url = licenseUrl }; } component.Licenses = new List <ComponentLicense> { new ComponentLicense { License = license } }; } } var projectUrl = nuspecReader.GetProjectUrl(); if (!string.IsNullOrEmpty(projectUrl)) { var externalReference = new Models.v1_2.ExternalReference(); externalReference.Type = Models.v1_2.ExternalReference.ExternalReferenceType.Website; externalReference.Url = projectUrl; component.ExternalReferences = new List <ExternalReference> { externalReference }; } // Source: https://docs.microsoft.com/de-de/nuget/reference/nuspec#repository var repoMeta = nuspecReader.GetRepositoryMetadata(); var vcsUrl = repoMeta?.Url; if (!string.IsNullOrEmpty(vcsUrl)) { var externalReference = new Models.v1_2.ExternalReference(); externalReference.Type = Models.v1_2.ExternalReference.ExternalReferenceType.Vcs; externalReference.Url = vcsUrl; if (null == component.ExternalReferences) { component.ExternalReferences = new List <ExternalReference> { externalReference }; } else { component.ExternalReferences.Add(externalReference); } } return(component); }
public async Task <Component> GetComponentAsync(string name, string version, Component.ComponentScope?scope) { if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(version)) { return(null); } // https://docs.microsoft.com/en-us/nuget/reference/nuget-client-sdk - Download a package var resource = await _sourceRepository.GetResourceAsync <FindPackageByIdResource>(); var component = SetupComponent(name, version, scope); var nuspecFilename = GetCachedNuspecFilename(name, version); var nuspecModel = await GetNuspec(name, version, nuspecFilename, resource).ConfigureAwait(false); if (nuspecModel.hashBytes != null) { var hex = BitConverter.ToString(nuspecModel.hashBytes).Replace("-", string.Empty); Hash h = new Hash { Alg = Hash.HashAlgorithm.SHA_512, Content = hex }; component.Hashes = new List <Hash> { h }; } if (nuspecModel.nuspecReader == null) { return(component); } component = SetupComponentProperties(component, nuspecModel); var licenseMetadata = nuspecModel.nuspecReader.GetLicenseMetadata(); if (licenseMetadata != null && licenseMetadata.Type == LicenseType.Expression) { Action <NuGetLicense> licenseProcessor = delegate(NuGetLicense nugetLicense) { var license = new License { Id = nugetLicense.Identifier, Name = nugetLicense.Identifier }; component.Licenses = new List <LicenseChoice> { new LicenseChoice { License = license } }; }; licenseMetadata.LicenseExpression.OnEachLeafNode(licenseProcessor, null); } else { var licenseUrl = nuspecModel.nuspecReader.GetLicenseUrl(); if (!string.IsNullOrEmpty(licenseUrl)) { License license = null; if (_githubService != null) { license = await _githubService.GetLicenseAsync(licenseUrl).ConfigureAwait(false); } if (license == null) { license = new License { Url = licenseUrl }; } component.Licenses = new List <LicenseChoice> { new LicenseChoice { License = license } }; } } var projectUrl = nuspecModel.nuspecReader.GetProjectUrl(); if (!string.IsNullOrEmpty(projectUrl)) { var externalReference = new ExternalReference { Type = ExternalReference.ExternalReferenceType.Website, Url = projectUrl }; component.ExternalReferences = new List <ExternalReference> { externalReference }; } // Source: https://docs.microsoft.com/de-de/nuget/reference/nuspec#repository var repoMeta = nuspecModel.nuspecReader.GetRepositoryMetadata(); var vcsUrl = repoMeta?.Url; if (!string.IsNullOrEmpty(vcsUrl)) { var externalReference = new ExternalReference { Type = ExternalReference.ExternalReferenceType.Vcs, Url = vcsUrl }; if (null == component.ExternalReferences) { component.ExternalReferences = new List <ExternalReference> { externalReference }; } else { component.ExternalReferences.Add(externalReference); } } return(component); }