Skip to content

Commit

Permalink
add Markdown serializer
Browse files Browse the repository at this point in the history
Signed-off-by: Hervé Boutemy <[email protected]>
  • Loading branch information
hboutemy committed Dec 22, 2022
1 parent 5de8d19 commit 6c1b2db
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 1 deletion.
11 changes: 10 additions & 1 deletion src/cyclonedx/CliUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ public static ConvertFormat AutoDetectConvertBomFormat(string filename)
{
return ConvertFormat.csv;
}
if (fileExtension == ".md")
{
return ConvertFormat.markdown;
}
else if (filename.ToLowerInvariant().EndsWith(".spdx.json", StringComparison.InvariantCulture))
{
return ConvertFormat.spdxjson;
Expand Down Expand Up @@ -116,7 +120,7 @@ public static async Task<Bom> InputBomHelper(string filename, ConvertFormat form
}
}


if (format == ConvertFormat.csv)
{
using var inputStream = filename == null ? Console.OpenStandardInput() : File.OpenRead(filename);
Expand Down Expand Up @@ -211,6 +215,11 @@ public static async Task<int> OutputBomHelper(Bom bom, ConvertFormat format, Spe
var bomBytes = Encoding.UTF8.GetBytes(bomString);
stream.Write(bomBytes);
break;
case ConvertFormat.markdown:
var mdString = MarkdownSerializer.Serialize(bom);
var mdBytes = Encoding.UTF8.GetBytes(mdString);
stream.Write(mdBytes);
break;
case ConvertFormat.spdxjson:
var spdxDoc = bom.ToSpdx();
await CycloneDX.Spdx.Serialization.JsonSerializer.SerializeAsync(spdxDoc, stream);
Expand Down
1 change: 1 addition & 0 deletions src/cyclonedx/Commands/ConvertFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ public enum ConvertFormat
protobuf,
csv,
spdxjson,
markdown,
}
}
197 changes: 197 additions & 0 deletions src/cyclonedx/Serialization/MarkdownSerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// This file is part of CycloneDX CLI Tool
//
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) OWASP Foundation. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Text;
using CycloneDX.Models;

namespace CycloneDX.Cli.Serialization
{
public static class MarkdownSerializer
{
public static string Serialize(Bom bom)
{
Contract.Requires(bom != null);
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
{
if (bom.Metadata?.Component != null)
{
writer.WriteLine("# " + bom.Metadata.Component.Name + " (" + bom.Metadata.Component.Type + ")");
}
writer.WriteLine("BOM " + bom.SerialNumber + " " + bom.BomFormat + " " + bom.SpecVersionString + " " + bom.Version + " " + bom.Metadata?.Timestamp);
writer.WriteLine();

if (bom.Metadata != null)
{
var m = bom.Metadata;

// BOM tools or authors
if (m.Tools != null)
{
writer.Write("BOM done with tools: ");
foreach (var t in m.Tools)
{
writer.Write(t.Name + " " + t.Version + " (" + t.Vendor + "), ");
}
writer.WriteLine();
}
else if (m.Authors != null)
{
writer.Write("BOM authored by: ");
foreach (var a in m.Authors)
{
writer.Write(a.Name + ", ");
}
writer.WriteLine();
}

// Component
if (m.Component != null)
{
var c = m.Component;

writer.Write(">");
if (c.Group != null)
{
writer.Write(" _group:_ **" + c.Group + "**");
}
if (c.Name != null)
{
writer.Write(" _name:_ **" + c.Name + "**");
}
if (c.Version != null)
{
writer.Write(" _version:_ **" + c.Version + "**");
}
if (c.Name == null && c.Purl != null)
{
writer.Write(" _purl:_ **" + c.Purl + "**");
}
if (c.Cpe != null)
{
writer.Write(" _CPE:_ **" + c.Cpe + "**");
}
writer.WriteLine();
if (c.Description != null)
{
writer.WriteLine(">");
writer.WriteLine("> " + c.Description);
}
writer.WriteLine();

if (c.ExternalReferences != null)
{
writer.Write("Component external references: ");
foreach (var er in c.ExternalReferences)
{
writer.Write("[" + er.Type + "](" + er.Url + "), ");
}
writer.WriteLine();
}
}

if (bom.ExternalReferences != null)
{
writer.WriteLine("## ExternalReferences");
writer.WriteLine("not supported yet"); // how is it different from bom.Metadata.Component.ExternalReferences?
writer.WriteLine();
}

if (bom.Components != null)
{
writer.WriteLine("## Components");
foreach (var c in bom.Components)
{
writer.Write("1. " + c.Type);
if (c.Group != null)
{
writer.Write(" _group:_ **" + c.Group + "**");
}
if (c.Name != null)
{
writer.Write(" _name:_ **" + c.Name + "**");
}
if (c.Version != null)
{
writer.Write(" _version:_ **" + c.Version + "**");
}
if (c.Scope != null)
{
writer.Write(" _scope:_ " + c.Scope);
}
if (c.Purl != null)
{
writer.WriteLine();
writer.Write(" _purl:_ " + c.Purl);
}
writer.WriteLine();
}
writer.WriteLine();
}

if (bom.Services != null)
{
writer.WriteLine("## Services");
writer.WriteLine("not supported yet");
writer.WriteLine();
}

if (bom.Dependencies != null) {
writer.WriteLine("## Dependencies");
WriteDependencies(writer, bom.Dependencies, "");
writer.WriteLine();
}

if (bom.Compositions != null)
{
writer.WriteLine("## Compositions");
writer.WriteLine("not supported yet");
writer.WriteLine();
}

if (bom.Vulnerabilities != null)
{
writer.WriteLine("## Vulnerabilities");
writer.WriteLine("not supported yet");
writer.WriteLine();
}
}
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
}

private static void WriteDependencies(StreamWriter writer, List<Dependency> dependencies, string indent)
{
foreach (var d in dependencies)
{
writer.WriteLine(indent + "- " + d.Ref);
if (d.Dependencies != null) {
WriteDependencies(writer, d.Dependencies, indent + " ");
}
}
}

public static Bom Deserialize(string csv)
{
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# commons-compress (Library)
BOM urn:uuid:381cbf4c-3009-4a42-a4d0-7188e72fbfac CycloneDX 1.4 1 25/10/2022 19:46:32

BOM done with tools: CycloneDX Maven plugin 2.7.1 (OWASP Foundation),
> _group:_ **org.apache.commons** _name:_ **commons-compress** _version:_ **1.22**
>
> Apache Commons Compress software defines an API for working with compression and archive formats. These include: bzip2, gzip, pack200, lzma, xz, Snappy, traditional Unix Compress, DEFLATE, DEFLATE64, LZ4, Brotli, Zstandard and ar, cpio, jar, tar, zip, dump, 7z, arj.
Component external references: [Website](https://www.apache.org/), [BuildSystem](https://github.com/apache/commons-parent/actions), [Distribution](https://repository.apache.org/service/local/staging/deploy/maven2), [IssueTracker](https://issues.apache.org/jira/browse/COMPRESS), [MailingList](https://mail-archives.apache.org/mod_mbox/commons-user/), [Vcs](https://gitbox.apache.org/repos/asf?p=commons-compress.git),
## Components
1. Library _group:_ **com.github.luben** _name:_ **zstd-jni** _version:_ **1.5.2-5** _scope:_ Required
_purl:_ pkg:maven/com.github.luben/[email protected]?type=jar
1. Library _group:_ **org.brotli** _name:_ **dec** _version:_ **0.1.2** _scope:_ Required
_purl:_ pkg:maven/org.brotli/[email protected]?type=jar
1. Library _group:_ **org.tukaani** _name:_ **xz** _version:_ **1.9** _scope:_ Required
_purl:_ pkg:maven/org.tukaani/[email protected]?type=jar
1. Library _group:_ **org.ow2.asm** _name:_ **asm** _version:_ **9.4** _scope:_ Required
_purl:_ pkg:maven/org.ow2.asm/[email protected]?type=jar
1. Library _group:_ **org.osgi** _name:_ **org.osgi.core** _version:_ **6.0.0** _scope:_ Optional
_purl:_ pkg:maven/org.osgi/[email protected]?type=jar

## Dependencies
- pkg:maven/org.apache.commons/[email protected]?type=jar
- pkg:maven/com.github.luben/[email protected]?type=jar
- pkg:maven/org.brotli/[email protected]?type=jar
- pkg:maven/org.tukaani/[email protected]?type=jar
- pkg:maven/org.ow2.asm/[email protected]?type=jar
- pkg:maven/org.osgi/[email protected]?type=jar
- pkg:maven/com.github.luben/[email protected]?type=jar
- pkg:maven/org.brotli/[email protected]?type=jar
- pkg:maven/org.tukaani/[email protected]?type=jar
- pkg:maven/org.ow2.asm/[email protected]?type=jar
- pkg:maven/org.osgi/[email protected]?type=jar

0 comments on commit 6c1b2db

Please sign in to comment.